{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f61ee669-d3b3-479d-b198-1fc190b75325",
   "metadata": {},
   "source": [
    "## 数据导入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0fe6af3d-449a-40a0-ab21-bfb53c1ff481",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0975b793-3911-4c67-a011-d70080117562",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(22213, 363)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>TICKER_SYMBOL</th>\n",
       "      <th>ACT_PUBTIME</th>\n",
       "      <th>PUBLISH_DATE</th>\n",
       "      <th>END_DATE_REP</th>\n",
       "      <th>END_DATE</th>\n",
       "      <th>REPORT_TYPE</th>\n",
       "      <th>FISCAL_PERIOD</th>\n",
       "      <th>MERGED_FLAG</th>\n",
       "      <th>ACCOUTING_STANDARDS</th>\n",
       "      <th>CURRENCY_CD</th>\n",
       "      <th>...</th>\n",
       "      <th>CA_TURNOVER</th>\n",
       "      <th>OPER_CYCLE</th>\n",
       "      <th>INVEN_TURNOVER</th>\n",
       "      <th>FA_TURNOVER</th>\n",
       "      <th>TFA_TURNOVER</th>\n",
       "      <th>DAYS_AP</th>\n",
       "      <th>DAYS_INVEN</th>\n",
       "      <th>TA_TURNOVER</th>\n",
       "      <th>AR_TURNOVER</th>\n",
       "      <th>FLAG</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>4019</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>CNY</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>8166</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>CNY</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>9063</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>CNY</td>\n",
       "      <td>...</td>\n",
       "      <td>1.3751</td>\n",
       "      <td>148.8938</td>\n",
       "      <td>7.424</td>\n",
       "      <td>20.9362</td>\n",
       "      <td>15.298</td>\n",
       "      <td>75.4337</td>\n",
       "      <td>48.4911</td>\n",
       "      <td>1.2774</td>\n",
       "      <td>3.5856</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>10083</td>\n",
       "      <td>4</td>\n",
       "      <td>4</td>\n",
       "      <td>4</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>CNY</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>11737</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>CNY</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 363 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "   TICKER_SYMBOL  ACT_PUBTIME  PUBLISH_DATE  END_DATE_REP  END_DATE  \\\n",
       "0           4019            3             3             2         1   \n",
       "1           8166            3             3             2         1   \n",
       "2           9063            3             3             2         1   \n",
       "3          10083            4             4             4         1   \n",
       "4          11737            3             3             2         1   \n",
       "\n",
       "  REPORT_TYPE  FISCAL_PERIOD  MERGED_FLAG ACCOUTING_STANDARDS CURRENCY_CD  \\\n",
       "0           A             12            1           CHAS_2007         CNY   \n",
       "1           A             12            1           CHAS_2007         CNY   \n",
       "2           A             12            1           CHAS_2007         CNY   \n",
       "3           A             12            1           CHAS_2007         CNY   \n",
       "4           A             12            1           CHAS_2007         CNY   \n",
       "\n",
       "   ...  CA_TURNOVER  OPER_CYCLE  INVEN_TURNOVER  FA_TURNOVER  TFA_TURNOVER  \\\n",
       "0  ...          NaN         NaN             NaN          NaN           NaN   \n",
       "1  ...          NaN         NaN             NaN          NaN           NaN   \n",
       "2  ...       1.3751    148.8938           7.424      20.9362        15.298   \n",
       "3  ...          NaN         NaN             NaN          NaN           NaN   \n",
       "4  ...          NaN         NaN             NaN          NaN           NaN   \n",
       "\n",
       "   DAYS_AP  DAYS_INVEN  TA_TURNOVER  AR_TURNOVER  FLAG  \n",
       "0      NaN         NaN          NaN          NaN   0.0  \n",
       "1      NaN         NaN          NaN          NaN   0.0  \n",
       "2  75.4337     48.4911       1.2774       3.5856   0.0  \n",
       "3      NaN         NaN          NaN          NaN   0.0  \n",
       "4      NaN         NaN          NaN          NaN   0.0  \n",
       "\n",
       "[5 rows x 363 columns]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 各公司导入财务报告\n",
    "data = pd.read_csv('5. 各公司财务报告.csv')\n",
    "display(data.shape)\n",
    "data.head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "276e8a0d-ed6f-424e-98b5-00893211e608",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(4163, 2)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>TICKER_SYMBOL</th>\n",
       "      <th>所属行业</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>4019</td>\n",
       "      <td>制造业</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>4213</td>\n",
       "      <td>制造业</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>8166</td>\n",
       "      <td>制造业</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>9063</td>\n",
       "      <td>批发和零售业</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>10083</td>\n",
       "      <td>信息传输、软件和信息技术服务业</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   TICKER_SYMBOL             所属行业\n",
       "0           4019              制造业\n",
       "1           4213              制造业\n",
       "2           8166              制造业\n",
       "3           9063           批发和零售业\n",
       "4          10083  信息传输、软件和信息技术服务业"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 导入公司对应行业\n",
    "industry = pd.read_excel('5. 公司对应行业.xlsx')\n",
    "# 重命名列：为了保证表合并的时候列名一致\n",
    "industry.rename(columns={'股票代码': 'TICKER_SYMBOL'}, inplace=True)\n",
    "# 股票代码类型转换为整数型\n",
    "industry['TICKER_SYMBOL'] = industry['TICKER_SYMBOL'].astype(int)\n",
    "display(industry.shape)\n",
    "industry.head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "260b60ad-7ec7-4745-af55-567d62edded5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>TICKER_SYMBOL</th>\n",
       "      <th>所属行业</th>\n",
       "      <th>ACT_PUBTIME</th>\n",
       "      <th>PUBLISH_DATE</th>\n",
       "      <th>END_DATE_REP</th>\n",
       "      <th>END_DATE</th>\n",
       "      <th>REPORT_TYPE</th>\n",
       "      <th>FISCAL_PERIOD</th>\n",
       "      <th>MERGED_FLAG</th>\n",
       "      <th>ACCOUTING_STANDARDS</th>\n",
       "      <th>...</th>\n",
       "      <th>CA_TURNOVER</th>\n",
       "      <th>OPER_CYCLE</th>\n",
       "      <th>INVEN_TURNOVER</th>\n",
       "      <th>FA_TURNOVER</th>\n",
       "      <th>TFA_TURNOVER</th>\n",
       "      <th>DAYS_AP</th>\n",
       "      <th>DAYS_INVEN</th>\n",
       "      <th>TA_TURNOVER</th>\n",
       "      <th>AR_TURNOVER</th>\n",
       "      <th>FLAG</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>4019</td>\n",
       "      <td>制造业</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>8166</td>\n",
       "      <td>制造业</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>9063</td>\n",
       "      <td>批发和零售业</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>...</td>\n",
       "      <td>1.3751</td>\n",
       "      <td>148.8938</td>\n",
       "      <td>7.424</td>\n",
       "      <td>20.9362</td>\n",
       "      <td>15.298</td>\n",
       "      <td>75.4337</td>\n",
       "      <td>48.4911</td>\n",
       "      <td>1.2774</td>\n",
       "      <td>3.5856</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>3 rows × 364 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "   TICKER_SYMBOL    所属行业  ACT_PUBTIME  PUBLISH_DATE  END_DATE_REP  END_DATE  \\\n",
       "0           4019     制造业            3             3             2         1   \n",
       "1           8166     制造业            3             3             2         1   \n",
       "2           9063  批发和零售业            3             3             2         1   \n",
       "\n",
       "  REPORT_TYPE  FISCAL_PERIOD  MERGED_FLAG ACCOUTING_STANDARDS  ...  \\\n",
       "0           A             12            1           CHAS_2007  ...   \n",
       "1           A             12            1           CHAS_2007  ...   \n",
       "2           A             12            1           CHAS_2007  ...   \n",
       "\n",
       "  CA_TURNOVER  OPER_CYCLE  INVEN_TURNOVER  FA_TURNOVER  TFA_TURNOVER  DAYS_AP  \\\n",
       "0         NaN         NaN             NaN          NaN           NaN      NaN   \n",
       "1         NaN         NaN             NaN          NaN           NaN      NaN   \n",
       "2      1.3751    148.8938           7.424      20.9362        15.298  75.4337   \n",
       "\n",
       "   DAYS_INVEN  TA_TURNOVER  AR_TURNOVER  FLAG  \n",
       "0         NaN          NaN          NaN   0.0  \n",
       "1         NaN          NaN          NaN   0.0  \n",
       "2     48.4911       1.2774       3.5856   0.0  \n",
       "\n",
       "[3 rows x 364 columns]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 数据合并  -  左合并\n",
    "data_merge = pd.merge(industry, data, how='right', on=['TICKER_SYMBOL'])\n",
    "data_merge.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "7d891fe2-10e2-45a3-97ec-2f86f1d268eb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "所属行业\n",
       "制造业    13131\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data_merge['所属行业'].value_counts().head(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "46ae1752-ff46-4c4e-81db-8950b5880e12",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>TICKER_SYMBOL</th>\n",
       "      <th>所属行业</th>\n",
       "      <th>ACT_PUBTIME</th>\n",
       "      <th>PUBLISH_DATE</th>\n",
       "      <th>END_DATE_REP</th>\n",
       "      <th>END_DATE</th>\n",
       "      <th>REPORT_TYPE</th>\n",
       "      <th>FISCAL_PERIOD</th>\n",
       "      <th>MERGED_FLAG</th>\n",
       "      <th>ACCOUTING_STANDARDS</th>\n",
       "      <th>...</th>\n",
       "      <th>CA_TURNOVER</th>\n",
       "      <th>OPER_CYCLE</th>\n",
       "      <th>INVEN_TURNOVER</th>\n",
       "      <th>FA_TURNOVER</th>\n",
       "      <th>TFA_TURNOVER</th>\n",
       "      <th>DAYS_AP</th>\n",
       "      <th>DAYS_INVEN</th>\n",
       "      <th>TA_TURNOVER</th>\n",
       "      <th>AR_TURNOVER</th>\n",
       "      <th>FLAG</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>4019</td>\n",
       "      <td>制造业</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>8166</td>\n",
       "      <td>制造业</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>11737</td>\n",
       "      <td>制造业</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>A</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>CHAS_2007</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>3 rows × 364 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "   TICKER_SYMBOL 所属行业  ACT_PUBTIME  PUBLISH_DATE  END_DATE_REP  END_DATE  \\\n",
       "0           4019  制造业            3             3             2         1   \n",
       "1           8166  制造业            3             3             2         1   \n",
       "4          11737  制造业            3             3             2         1   \n",
       "\n",
       "  REPORT_TYPE  FISCAL_PERIOD  MERGED_FLAG ACCOUTING_STANDARDS  ...  \\\n",
       "0           A             12            1           CHAS_2007  ...   \n",
       "1           A             12            1           CHAS_2007  ...   \n",
       "4           A             12            1           CHAS_2007  ...   \n",
       "\n",
       "  CA_TURNOVER  OPER_CYCLE  INVEN_TURNOVER  FA_TURNOVER  TFA_TURNOVER  DAYS_AP  \\\n",
       "0         NaN         NaN             NaN          NaN           NaN      NaN   \n",
       "1         NaN         NaN             NaN          NaN           NaN      NaN   \n",
       "4         NaN         NaN             NaN          NaN           NaN      NaN   \n",
       "\n",
       "   DAYS_INVEN  TA_TURNOVER  AR_TURNOVER  FLAG  \n",
       "0         NaN          NaN          NaN   0.0  \n",
       "1         NaN          NaN          NaN   0.0  \n",
       "4         NaN          NaN          NaN   0.0  \n",
       "\n",
       "[3 rows x 364 columns]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 提取【制造业】的企业的数据\n",
    "datas_manual = data_merge[data_merge['所属行业']=='制造业']\n",
    "datas_manual.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "92dc26a9-c296-4900-b4a9-4d2c00c12e5d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "END_DATE\n",
       "5    2500\n",
       "4    2242\n",
       "3    2094\n",
       "2    2031\n",
       "1    1764\n",
       "Name: count, dtype: int64"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "END_DATE\n",
       "6    2500\n",
       "Name: count, dtype: int64"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 筛选训练的数据(前五年) 和 最终预测的数据(第六年)\n",
    "datas_manual_y5 = datas_manual[datas_manual['END_DATE'] != 6]\n",
    "datas_manual_y6 = datas_manual[datas_manual['END_DATE'] == 6]\n",
    "display(datas_manual_y5['END_DATE'].value_counts())\n",
    "display(datas_manual_y6['END_DATE'].value_counts())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "468bf9b7-352f-4ab4-ae5f-25fcd0e18fa1",
   "metadata": {},
   "source": [
    "## 数据预处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "696f96a4-f964-42f6-9aff-cd8f2dc2aa68",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = datas_manual_y5.copy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d94632b-e23d-46a5-b996-bdf4c4100b0a",
   "metadata": {},
   "source": [
    "### 剔除无用特征"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "7290d6d8-d748-4d65-a427-60af5a0fb115",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 剔除无效特征列表\n",
    "drop_columns = [\n",
    "    'TICKER_SYMBOL', 'ACT_PUBTIME', 'PUBLISH_DATE', 'END_DATE_REP', \n",
    "    'END_DATE', 'REPORT_TYPE', 'FISCAL_PERIOD', 'MERGED_FLAG', \n",
    "    'ACCOUTING_STANDARDS', 'CURRENCY_CD', 'T_LIAB_EQUITY'\n",
    "]\n",
    "\n",
    "df = df.drop(columns=drop_columns, errors='ignore')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07b9058f-f06e-43a9-b813-f63fd61e0b07",
   "metadata": {},
   "source": [
    "### 缺失值处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "27ddfe94-909f-477c-8ece-9747e2c12b6b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10631, 337)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 去除只有一个值的特征\n",
    "df=df.loc[:,(df.nunique()!=1)|(df.columns==\"FLAG\")]\n",
    "df.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "3ec53bdf-6484-434e-8b22-21d1a5096deb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.FLAG.isnull().sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "5d132f3a-1355-4403-aac6-4cfbd09ee638",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10631, 89)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 思路2：缺失率 大于50% 的特征\n",
    "df = df.loc[:,(df.isnull().sum()<len(df)*0.5)|(df.columns==\"FLAG\")]\n",
    "df.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "7a8b99b5-b31f-4075-9815-3b1627e733ef",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10631, 89)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 思路1：缺失率 大于50% 样本\n",
    "df = df[df.isnull().sum(axis = 1)<len(df.columns)*0.5]\n",
    "df.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "dcf98368-29ed-44f6-90cb-bc7aaceeffdf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>CASH_C_EQUIV</th>\n",
       "      <th>NOTES_RECEIV</th>\n",
       "      <th>AR</th>\n",
       "      <th>PREPAYMENT</th>\n",
       "      <th>OTH_RECEIV</th>\n",
       "      <th>INVENTORIES</th>\n",
       "      <th>OTH_CA</th>\n",
       "      <th>T_CA</th>\n",
       "      <th>AVAIL_FOR_SALE_FA</th>\n",
       "      <th>FIXED_ASSETS</th>\n",
       "      <th>...</th>\n",
       "      <th>COGS</th>\n",
       "      <th>N_INCOME</th>\n",
       "      <th>BIZ_TAX_SURCHG</th>\n",
       "      <th>NOPERATE_EXP</th>\n",
       "      <th>COMPR_INC_ATTR_M_S</th>\n",
       "      <th>INCOME_TAX</th>\n",
       "      <th>NOPERATE_INCOME</th>\n",
       "      <th>MINORITY_GAIN</th>\n",
       "      <th>T_COGS</th>\n",
       "      <th>FLAG</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>6.719939e+08</td>\n",
       "      <td>1.643520e+08</td>\n",
       "      <td>3.451945e+08</td>\n",
       "      <td>1.039522e+07</td>\n",
       "      <td>3584940.60</td>\n",
       "      <td>9.372176e+07</td>\n",
       "      <td>3.802205e+07</td>\n",
       "      <td>1.291554e+09</td>\n",
       "      <td>25002000.0</td>\n",
       "      <td>5.634969e+08</td>\n",
       "      <td>...</td>\n",
       "      <td>2.935500e+08</td>\n",
       "      <td>1.054685e+08</td>\n",
       "      <td>1505596.10</td>\n",
       "      <td>224194.93</td>\n",
       "      <td>5.048739e+05</td>\n",
       "      <td>19509143.39</td>\n",
       "      <td>16781651.83</td>\n",
       "      <td>518851.39</td>\n",
       "      <td>3.885748e+08</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1.010981e+09</td>\n",
       "      <td>2.155752e+09</td>\n",
       "      <td>2.887470e+08</td>\n",
       "      <td>1.075202e+08</td>\n",
       "      <td>85626756.05</td>\n",
       "      <td>1.049809e+09</td>\n",
       "      <td>1.080342e+07</td>\n",
       "      <td>4.709240e+09</td>\n",
       "      <td>25002000.0</td>\n",
       "      <td>6.487973e+08</td>\n",
       "      <td>...</td>\n",
       "      <td>3.498736e+09</td>\n",
       "      <td>3.626590e+08</td>\n",
       "      <td>28213513.69</td>\n",
       "      <td>1071702.74</td>\n",
       "      <td>5.048739e+05</td>\n",
       "      <td>52563706.01</td>\n",
       "      <td>22480726.69</td>\n",
       "      <td>518851.39</td>\n",
       "      <td>4.930772e+09</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1.502023e+09</td>\n",
       "      <td>2.688988e+07</td>\n",
       "      <td>9.517806e+08</td>\n",
       "      <td>4.157376e+07</td>\n",
       "      <td>37519236.14</td>\n",
       "      <td>6.611381e+08</td>\n",
       "      <td>3.919438e+08</td>\n",
       "      <td>3.619333e+09</td>\n",
       "      <td>1500000.0</td>\n",
       "      <td>5.680283e+08</td>\n",
       "      <td>...</td>\n",
       "      <td>7.883673e+08</td>\n",
       "      <td>3.479212e+08</td>\n",
       "      <td>8298888.47</td>\n",
       "      <td>633458.95</td>\n",
       "      <td>2.172267e+07</td>\n",
       "      <td>36404446.16</td>\n",
       "      <td>60365828.87</td>\n",
       "      <td>21722671.14</td>\n",
       "      <td>1.384902e+09</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>9.966031e+08</td>\n",
       "      <td>3.686740e+05</td>\n",
       "      <td>2.824134e+08</td>\n",
       "      <td>2.741431e+07</td>\n",
       "      <td>67249473.03</td>\n",
       "      <td>3.400061e+08</td>\n",
       "      <td>8.145214e+08</td>\n",
       "      <td>2.554056e+09</td>\n",
       "      <td>25002000.0</td>\n",
       "      <td>4.373165e+08</td>\n",
       "      <td>...</td>\n",
       "      <td>1.743231e+09</td>\n",
       "      <td>1.043842e+08</td>\n",
       "      <td>11585500.32</td>\n",
       "      <td>1727998.62</td>\n",
       "      <td>3.681052e+04</td>\n",
       "      <td>17533501.14</td>\n",
       "      <td>18113878.30</td>\n",
       "      <td>36810.52</td>\n",
       "      <td>2.153059e+09</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>5.763404e+07</td>\n",
       "      <td>8.990000e+06</td>\n",
       "      <td>5.941825e+07</td>\n",
       "      <td>3.603420e+07</td>\n",
       "      <td>775584.93</td>\n",
       "      <td>6.985958e+07</td>\n",
       "      <td>4.721015e+05</td>\n",
       "      <td>2.331838e+08</td>\n",
       "      <td>25002000.0</td>\n",
       "      <td>6.166910e+07</td>\n",
       "      <td>...</td>\n",
       "      <td>2.986392e+08</td>\n",
       "      <td>5.190705e+07</td>\n",
       "      <td>1621817.64</td>\n",
       "      <td>499429.33</td>\n",
       "      <td>9.192152e+05</td>\n",
       "      <td>8519689.96</td>\n",
       "      <td>4847047.58</td>\n",
       "      <td>919215.16</td>\n",
       "      <td>3.384751e+08</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 89 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "   CASH_C_EQUIV  NOTES_RECEIV            AR    PREPAYMENT   OTH_RECEIV  \\\n",
       "0  6.719939e+08  1.643520e+08  3.451945e+08  1.039522e+07   3584940.60   \n",
       "1  1.010981e+09  2.155752e+09  2.887470e+08  1.075202e+08  85626756.05   \n",
       "4  1.502023e+09  2.688988e+07  9.517806e+08  4.157376e+07  37519236.14   \n",
       "6  9.966031e+08  3.686740e+05  2.824134e+08  2.741431e+07  67249473.03   \n",
       "7  5.763404e+07  8.990000e+06  5.941825e+07  3.603420e+07    775584.93   \n",
       "\n",
       "    INVENTORIES        OTH_CA          T_CA  AVAIL_FOR_SALE_FA  FIXED_ASSETS  \\\n",
       "0  9.372176e+07  3.802205e+07  1.291554e+09         25002000.0  5.634969e+08   \n",
       "1  1.049809e+09  1.080342e+07  4.709240e+09         25002000.0  6.487973e+08   \n",
       "4  6.611381e+08  3.919438e+08  3.619333e+09          1500000.0  5.680283e+08   \n",
       "6  3.400061e+08  8.145214e+08  2.554056e+09         25002000.0  4.373165e+08   \n",
       "7  6.985958e+07  4.721015e+05  2.331838e+08         25002000.0  6.166910e+07   \n",
       "\n",
       "   ...          COGS      N_INCOME  BIZ_TAX_SURCHG  NOPERATE_EXP  \\\n",
       "0  ...  2.935500e+08  1.054685e+08      1505596.10     224194.93   \n",
       "1  ...  3.498736e+09  3.626590e+08     28213513.69    1071702.74   \n",
       "4  ...  7.883673e+08  3.479212e+08      8298888.47     633458.95   \n",
       "6  ...  1.743231e+09  1.043842e+08     11585500.32    1727998.62   \n",
       "7  ...  2.986392e+08  5.190705e+07      1621817.64     499429.33   \n",
       "\n",
       "   COMPR_INC_ATTR_M_S   INCOME_TAX  NOPERATE_INCOME  MINORITY_GAIN  \\\n",
       "0        5.048739e+05  19509143.39      16781651.83      518851.39   \n",
       "1        5.048739e+05  52563706.01      22480726.69      518851.39   \n",
       "4        2.172267e+07  36404446.16      60365828.87    21722671.14   \n",
       "6        3.681052e+04  17533501.14      18113878.30       36810.52   \n",
       "7        9.192152e+05   8519689.96       4847047.58      919215.16   \n",
       "\n",
       "         T_COGS  FLAG  \n",
       "0  3.885748e+08   0.0  \n",
       "1  4.930772e+09   0.0  \n",
       "4  1.384902e+09   0.0  \n",
       "6  2.153059e+09   0.0  \n",
       "7  3.384751e+08   0.0  \n",
       "\n",
       "[5 rows x 89 columns]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 思路3：缺失值填充\n",
    "df=df.fillna(df.median())\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2bd79e44-979d-4195-84dd-3bad3b66ca05",
   "metadata": {},
   "source": [
    "### 异常值处理"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6cf582bd-7ba0-4d75-b170-b20d091e39bd",
   "metadata": {},
   "source": [
    "### 划分数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "9e05029d-3d79-4c74-bcde-a7b5eb78eefe",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "data_x = df.iloc[:,:-1]\n",
    "data_y = df.iloc[:,-1]\n",
    "\n",
    "X_train, X_test, y_train, y_test = train_test_split(data_x, data_y, \n",
    "                                                    test_size=0.33, random_state=42)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52655992-3325-47ea-a352-74a4ba93a962",
   "metadata": {},
   "source": [
    "### 标准化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "2aa62734-99b8-4a3d-b35f-8e9119a94f0f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(7122, 88)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "(3509, 88)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "# 创建标准化器\n",
    "scaler = StandardScaler()\n",
    "\n",
    "# 只在训练集上拟合（计算均值和标准差）\n",
    "scaler.fit(X_train)\n",
    "\n",
    "# 用训练集的统计量转换训练集和测试集\n",
    "X_train_scaled = scaler.transform(X_train)\n",
    "X_train_scaled = pd.DataFrame(X_train_scaled, index = X_train.index, columns = X_train.columns)\n",
    "display(X_train_scaled.shape)\n",
    "\n",
    "X_test_scaled = scaler.transform(X_test)\n",
    "X_test_scaled = pd.DataFrame(X_test_scaled, index = X_test.index, columns = X_test.columns)\n",
    "display(X_test_scaled.shape)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9e505f8-fa2f-4009-a877-3253cccc42b0",
   "metadata": {},
   "source": [
    "## 特征工程"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb0da287-c745-4433-8f27-6cc6ec49365f",
   "metadata": {},
   "source": [
    "#### 相关性阈值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "5ee890ee-4c1c-423b-92af-c0d46400336a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 热力相关\n",
    "corr_matrix = X_train_scaled.corr().abs()\n",
    "# 找到相关性大于 0.9 的特征对\n",
    "high_corr = np.array([\n",
    "    (i, j) for i in corr_matrix.columns for j in corr_matrix.columns \n",
    "    if (i != j and corr_matrix.loc[i, j] > 0.9)\n",
    "])\n",
    "\n",
    "X_train_scaled = X_train_scaled.drop(columns=high_corr[:,1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41d05a19-3587-4d29-9113-76fb655b13dd",
   "metadata": {},
   "source": [
    "#### 互信息"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "d6b7f3ac-f2b6-41bd-aa11-5fbbd1acbeb9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "互信息选择的特征： Index(['NOTES_RECEIV', 'AR', 'PREPAYMENT', 'OTH_RECEIV', 'INVENTORIES',\n",
      "       'OTH_CA', 'CIP', 'DEFER_TAX_ASSETS', 'ST_BORR', 'NOTES_PAYABLE',\n",
      "       'ADVANCE_RECEIPTS', 'PAYROLL_PAYABLE', 'TAXES_PAYABLE',\n",
      "       'PAID_IN_CAPITAL', 'CAPITAL_RESER', 'SURPLUS_RESER',\n",
      "       'RETAINED_EARNINGS', 'MINORITY_INT', 'C_PAID_OTH_FINAN_A',\n",
      "       'N_CF_FR_INVEST_A', 'N_CF_OPERATE_A', 'C_PAID_FOR_OTH_OP_A',\n",
      "       'REFUND_OF_TAX', 'N_CHANGE_IN_CASH', 'FOREX_EFFECTS',\n",
      "       'C_PAID_FOR_TAXES', 'C_PAID_DIV_PROF_INT', 'C_FR_OTH_INVEST_A',\n",
      "       'C_FR_OTH_OPERATE_A', 'DISP_FIX_ASSETS_OTH', 'N_CF_FR_FINAN_A',\n",
      "       'PUR_FIX_ASSETS_OTH', 'DILUTED_EPS', 'BASIC_EPS', 'ASSETS_IMPAIR_LOSS',\n",
      "       'FINAN_EXP', 'SELL_EXP', 'BIZ_TAX_SURCHG', 'NOPERATE_EXP',\n",
      "       'NOPERATE_INCOME'],\n",
      "      dtype='object')\n"
     ]
    }
   ],
   "source": [
    "from sklearn.feature_selection import SelectKBest, chi2, mutual_info_classif\n",
    "# 互信息（不要求非负）\n",
    "mi_selector = SelectKBest(mutual_info_classif, k=40)\n",
    "X_train_mi = mi_selector.fit_transform(X_train_scaled, y_train)\n",
    "\n",
    "# 查看选择的特征\n",
    "selected_features = X_train_scaled.columns[mi_selector.get_support()]\n",
    "print(\"互信息选择的特征：\", selected_features)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "1802a158-ea1d-472b-a989-870e2c653d4a",
   "metadata": {},
   "outputs": [],
   "source": [
    "selected_ft = selected_features.values.tolist()\n",
    "feature_lst = selected_ft.copy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2093dfef-3812-4ec4-b9bd-8df4c5a7ce36",
   "metadata": {},
   "source": [
    "#### 不均衡学习"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "2f7a9313-f1d7-475c-9fd6-f26e389e484e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'y_train'"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "FLAG\n",
       "0.0    7077\n",
       "1.0      45\n",
       "Name: count, dtype: int64"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from imblearn.over_sampling import SMOTE\n",
    "sm = SMOTE(sampling_strategy='minority', random_state=0)\n",
    "display(\"y_train\",y_train.value_counts())\n",
    "# 训练随机采样模型\n",
    "x_train_sm, y_train_sm = sm.fit_resample(X_train_scaled, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "a6f93a78-07b9-427d-af63-bc7e41c7ee2a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'x_train_sm'"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "(14154, 40)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "'y_train_sm'"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "FLAG\n",
       "0.0    7077\n",
       "1.0    7077\n",
       "Name: count, dtype: int64"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 训练集\n",
    "x_train_sm = x_train_sm[feature_lst]\n",
    "display(\"x_train_sm\",x_train_sm.shape)\n",
    "display(\"y_train_sm\",y_train_sm.value_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "4495a9f9-742b-4fbb-bf26-844240b06c1f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'X_test'"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "(3509, 40)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "'y_test'"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "FLAG\n",
       "0.0    3470\n",
       "1.0      39\n",
       "Name: count, dtype: int64"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 测试集\n",
    "X_test = X_test_scaled[feature_lst]\n",
    "display(\"X_test\",X_test.shape)\n",
    "display(\"y_test\",y_test.value_counts())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3daee0ae-2c5d-48f6-a8bf-9f3425b01a65",
   "metadata": {},
   "source": [
    "## 模型建立"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "b1ab459b-e1d2-4456-814a-b91e27b10e68",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.model_selection import cross_val_score\n",
    "from sklearn.model_selection import GridSearchCV\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.ensemble import RandomForestClassifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "49ecba1e-89f4-45b4-9975-43a4ea3e39a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "x_train, _, y_train, _ = train_test_split(\n",
    "    x_train_sm, \n",
    "    y_train_sm, \n",
    "    train_size=0.2, # 只取20%的数据\n",
    "    stratify=y_train_sm, # 关键！按目标变量y进行分层\n",
    "    random_state=42  # 固定随机种子，保证结果可复现\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "dd28a7a9-e233-4eb9-a147-1a3ba1fa6002",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9876325088339222"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 随机森林模型\n",
    "rf = RandomForestClassifier(n_estimators=100, random_state=42)\n",
    "rf.fit(x_train, y_train)\n",
    "cross_s = cross_val_score(rf, x_train, y_train, cv=5).mean()\n",
    "cross_s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "2561750b-cf69-4ead-ab5f-90fdbf01059c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cv: 0.9876325088339222\n",
      "rf: 0.9737817041892277\n"
     ]
    }
   ],
   "source": [
    "score = rf.score(X_test, y_test)\n",
    "print('cv:',cross_s)\n",
    "print('rf:',score)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "6fa62ef3-15ce-44cc-8515-fc1cfa23c963",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test AUC: 0.7312236754599867\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import roc_auc_score\n",
    "# 用 predict_proba 得到正类(1)的概率\n",
    "y_prob = rf.predict_proba(X_test)[:, 1]\n",
    "# 计算 AUC\n",
    "auc = roc_auc_score(y_test, y_prob)\n",
    "print(\"Test AUC:\", auc)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f13a9e09-a1c3-4f5b-980c-bbf517a24c15",
   "metadata": {},
   "source": [
    "### 调参"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c2c0e78-60c4-49ed-8efd-dbc9585f7ae1",
   "metadata": {},
   "source": [
    "- 大范围调整 n_estimators"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "1c8457dd-f698-4341-a9c0-6cf2472614f6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "151 0.9886925795053004\n"
     ]
    },
    {
     "data": {
      "image/png": "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bFnI12bMmBH8e05Ojr75zW9qxIgR+vDDDzV8+PBoN/WUdPbn1s73VpJWrlypW265RQkJCSHH7Xhv23vWSNH5vWVILoLS0tLkdDpbJdjDhw+3SsN29ZOf/ESvvfaa3nnnHWVmZp7w3IyMDA0aNEh79uyJUusiIzExUeeee6727NkTXC3XHe/xV199pfXr1+vOO+884Xnd5b525F727dtXjY2NKisra/ccO/F6vbrxxhu1d+9e5eXlhd3Nfvjw4XK5XLa/11Lrn9vudm8laePGjdq1a1fY32HJ+ve2vWdNNH9vCUwRFBcXp9zc3FZdnHl5eRozZoxJreoahmFo9uzZWrt2rd5++20NHjw47HuOHDmi/fv3KyMjIwotjJyGhgbt2LFDGRkZwS7tY+9xY2Oj3n33Xdvf4+eff159+vTRNddcc8Lzust97ci9zM3NlcvlCjmnqKhI27Zts939DoSlPXv2aP369TrjjDPCvuezzz6T1+u1/b2WWv/cdqd7G/Dcc88pNzdX559/fthzrXpvwz1rovp7eyqz1RHe6tWrDZfLZTz33HPG9u3bjTlz5hiJiYnGvn37zG7aKfnxj39spKSkGBs2bDCKioqCr9raWsMwDKOqqsq47777jE2bNhl79+413nnnHWP06NFG//79jcrKSpNbf3Luu+8+Y8OGDcaXX35p/Otf/zImTpxoJCcnB+/ho48+aqSkpBhr1641Pv30U+Omm24yMjIybHedx/L5fMbAgQON+++/P+S43e9rVVWVsXXrVmPr1q2GJGPp0qXG1q1bgyvDOnIvZ86caWRmZhrr1683PvzwQ+OKK64wzj//fKOpqcmsy2rTia7V6/Ua1157rZGZmWl89NFHIb/DDQ0NhmEYxueff2489NBDxubNm429e/car7/+ujFs2DDjggsusNy1GsaJr7ejP7fd4d4GVFRUGD169DCWL1/e6v12urfhnjWGEb3fWwJTFDz11FPGoEGDjLi4OGP48OEhS+/tSlKbr+eff94wDMOora01xo0bZ/Tu3dtwuVzGwIEDjdtvv90oLCw0t+GdMHXqVCMjI8NwuVxGv379jO985zvGZ599Fvy63+83HnzwQaNv375GfHy8cckllxiffvqpiS0+dX//+98NScauXbtCjtv9vr7zzjtt/tzefvvthmF07F7W1dUZs2fPNnr16mW43W5j4sSJlrz+E13r3r172/0dfueddwzDMIzCwkLjkksuMXr16mXExcUZZ511lnHXXXcZR44cMffC2nGi6+3oz213uLcBK1asMNxut1FeXt7q/Xa6t+GeNYYRvd9bx9EGAQAAoB3MYQIAAAiDwAQAABAGgQkAACAMAhMAAEAYBCYAAIAwCEwAAABhEJgAAADCIDABAACEQWAC0C1lZWXpiSeeMLsZALoJAhMAW3vhhReUmpra6vjmzZv1wx/+MOKfTzADTg+xZjcAACKhd+/eZjfhpDQ2NiouLs7sZgBoBz1MALrEZZddprvuuks///nP1atXL/Xt21cLFizo0HsrKir0wx/+UH369JHH49EVV1yhjz/+OPj1jz/+WJdffrmSk5Pl8XiUm5urLVu2aMOGDfr+97+viooKORwOORyO4Gce3/PjcDi0YsUKTZw4UT169FB2drbef/99ff7557rsssuUmJio0aNH64svvgi+54svvtDkyZOVnp6upKQkjRw5UuvXrw+55q+++kr33HNP8PMD/u///k/nnHOO4uPjlZWVpSVLloRcc1ZWln75y19q+vTpSklJ0YwZM9TY2KjZs2crIyNDCQkJysrK0qJFi07iLgCIFAITgC6zatUqJSYm6oMPPtBjjz2mhQsXKi8v74TvMQxD11xzjYqLi7Vu3ToVFBRo+PDh+va3v63S0lJJ0i233KLMzExt3rxZBQUFeuCBB+RyuTRmzBg98cQT8ng8KioqUlFRkX7605+2+1kPP/ywbrvtNn300UcaNmyYbr75Zv3oRz/S3LlztWXLFknS7Nmzg+dXV1frP/7jP7R+/Xpt3bpV48eP16RJk1RYWChJWrt2rTIzM7Vw4cLg50tSQUGBbrzxRk2bNk2ffvqpFixYoPnz5+uFF14Iac/ixYuVk5OjgoICzZ8/X//zP/+j1157TX/84x+1a9cuvfTSS8rKyjrZ2wAgEgwA6AKXXnqpcdFFF4UcGzlypHH//fef8H1vvfWW4fF4jPr6+pDjZ511lrFixQrDMAwjOTnZeOGFF9p8//PPP2+kpKS0Oj5o0CDj8ccfD/5bkjFv3rzgv99//31DkvHcc88Fj/3hD38wEhISTtjes88+2/jf//3fdj/HMAzj5ptvNq666qqQYz/72c+Ms88+O+R9U6ZMCTnnJz/5iXHFFVcYfr//hG0AEH30MAHoMuedd17IvzMyMnT48OETvqegoEDV1dU644wzlJSUFHzt3bs3ODx277336s4779SVV16pRx99NGTYrLPtS09PlySde+65Icfq6+tVWVkpSaqpqdHPf/5znX322UpNTVVSUpJ27twZ7GFqz44dOzR27NiQY2PHjtWePXvk8/mCx0aMGBFyzvTp0/XRRx9p6NChuuuuu/Tmm2926joBdD0mfQPoMi6XK+TfDodDfr//hO/x+/3KyMjQhg0bWn0tsPptwYIFuvnmm/X666/rjTfe0IMPPqjVq1fruuuu63T7AvON2joWaPPPfvYz/f3vf9dvfvMbfeMb35Db7db111+vxsbGE36OYRgh85kCx46XmJgY8u/hw4dr7969euONN7R+/XrdeOONuvLKK/XKK6+cxFUCiAQCEwBTDR8+XMXFxYqNjT3hfJ0hQ4ZoyJAhuueee3TTTTfp+eef13XXXae4uLiQXpuutHHjRk2fPj0YzKqrq7Vv376Qc9r6/LPPPlvvvfdeyLFNmzZpyJAhcjqdJ/xMj8ejqVOnaurUqbr++ut19dVXq7S0VL169Tr1CwLQaQzJATDVlVdeqdGjR2vKlCn6+9//rn379mnTpk2aN2+etmzZorq6Os2ePVsbNmzQV199pX/+85/avHmzsrOzJTWvNquurtZbb72lkpIS1dbWdlnbvvGNb2jt2rX66KOP9PHHH+vmm29u1WOWlZWlf/zjHzpw4IBKSkokSffdd5/eeustPfzww9q9e7dWrVqlJ5988oQT0iXp8ccf1+rVq7Vz507t3r1bf/rTn9S3b98260wBiC4CEwBTORwOrVu3Tpdccol+8IMfaMiQIZo2bZr27dun9PR0OZ1OHTlyRLfddpuGDBmiG2+8URMmTNBDDz0kSRozZoxmzpypqVOnqnfv3nrssce6rG2PP/64evbsqTFjxmjSpEkaP368hg8fHnLOwoULtW/fPp111lnB2k/Dhw/XH//4R61evVo5OTn6r//6Ly1cuFDTp08/4eclJSXp17/+tUaMGKGRI0dq3759WrdunWJi+J9qwGwOo62BdQAAAATxf1sAAADCIDABiKiXX345pFzAsa9zzjnH7OYBQIcwJAcgoqqqqnTo0KE2v+ZyuTRo0KAotwgATh6BCQAAIAyG5AAAAMIgMAEAAIRBYAIAAAiDwAQAABAGgQkAACAMAhMAAEAYBCYAAIAwCEwAAABh/H8/V5HjeVzkKwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "cross = []\n",
    "for i  in range(0, 200, 10):\n",
    "    rf = RandomForestClassifier(n_estimators=i+1,n_jobs=-1, random_state=42)\n",
    "    rf.fit(x_train, y_train)\n",
    "    cross_score = cross_val_score(rf, x_train, y_train, cv=5).mean()\n",
    "    cross.append(cross_score)\n",
    "plt.plot(range(1,201,10), cross)\n",
    "plt.xlabel('n_estimators')\n",
    "plt.ylabel('acc') # 评分使用的是准确率（即cross_val_score的返回值）\n",
    "print((cross.index(max(cross))*10)+1, max(cross))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53e8cb38-3426-4732-bba1-bb30dff9b86c",
   "metadata": {},
   "source": [
    "- 小范围调整 n_estimators"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "5368d3da-eed8-4e35-b469-4a889ac2e95b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "35 0.9872791519434629\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlIAAAGxCAYAAACp51jCAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABgdUlEQVR4nO3deVhU9f4H8PeZYRiGXWUXBFxAFDIFQ4Fy17iKS2UuZXnLrpb9SlvlpqmY0HI1bzflpmZpWtgtU1O8ppamYrKoqYiAAoIIIsgq+8z5/TEyNwRNETgzw/v1PPM8cuY7M5+ZI87bcz7n+xVEURRBRERERPdMJnUBRERERIaKQYqIiIiohRikiIiIiFqIQYqIiIiohRikiIiIiFqIQYqIiIiohRikiIiIiFqIQYqIiIiohUykLsCYaTQaXLlyBVZWVhAEQepyiIiI6C6Ioojy8nK4uLhAJrvzMScGqTZ05coVuLm5SV0GERERtUBOTg5cXV3vOIZBqg1ZWVkB0O4Ia2triashIiKiu1FWVgY3Nzfd9/idMEi1oYbTedbW1gxSREREBuZu2nLYbE5ERETUQgxSRERERC3EIEVERETUQgxSRERERC3EIEVERETUQgxSRERERC3EIEVERETUQgxSRERERC3EIEVERETUQgxSRERERC3EIEVERETUQgxSRERERC3EIEXUCrKLKlFRUy91GURE1M4YpIju0+H0axi24iBe3JwkdSlERNTOGKSI7kNNvRrv7kiGWiPiyIVCFFbUSF0SERG1IwYpovvw+ZFMZBbeAACIIvDL+QKJKyIiovbEIEXUQldKqvCvAxcAAD7O1gCAnxmkiIg6FAYpohZaHpuCqjo1Bnp0QtRjfgCAX9OuobZeI3FlRETUXhikiFrg6IVC7D6dB5kALB3viwe62sDeSokbtWoczyySujwiImonDFJE96i2XoPFO5MBADMGuaOPizVkMgHDvR0AAAdSeHqPiKijYJAiukcb47JwoaACXSxM8dpob9324T43g9T5qxBFUaryiIioHTFIEd2Dq2XVWLU/DQDw9qO9YaNS6O4L6WkHU7kMOdercKGgQqoSiYioHTFIEd2DyNgU3KhV40E3Wzzh79roPgulCQb36AIAOMCr94iIOgQGKaK7dDyjCDtOXYEgAMsm+EImE5qMGXHz9N7P7JMiIuoQGKSI7kK9+n8N5tMe6gY/V5tmxw3vrQ1SiZeuo/hGbbvVR0RE0mCQIroLm45dwvn8ctiaK/DmHxrMb+XayRy9naygEYFDadfasUIiIpICgxTRn7hWXoOP92kbzN8a0xudLEzvOL7hqBT7pIiIjB+DFNGfeH/PeZTX1MOvqw2mDHT70/ENfVIHUwtQp+Ys50RExoxBiugOki5dx/cnLgMAIib0hbyZBvNbPejWCZ0tTFFeXY/ErOK2LpGIiCTEIEV0G2qNiEXbtQ3mUwLc0L9bp7t6nFwmYKi3PQDg5/NX26w+IiKSHoMU0W18ffwSzuWVwdrMBG89evsG8+aM9HEEwOViiIiMHYMUUTOKKmrw0d5UAMAbY7zRxVJ5T49/uJcdTGQCMgpvIOMaZzknIjJWDFJEzfhobyrKquvRx9kaTwW63/PjrcwUCOzeGQDwM6/eIyIyWgxSRLc4lVOCrYk5AO6+wbw5I3rz9B4RkbFjkCL6A7VGxLs7zkIUgccGdEWAR+cWP1fDNAgJWddRWlXXWiUSEZEeYZAi+oNvE3Nw+nIprJQmWBDa+76ey72LBXrYW6BeI+JwOmc5JyIyRgxSRDeVVNbiw/+eBwDMG+UFByuz+35OXr1HRGTcGKSIbvpobyqKK+vg7WiFZwffe4N5cxqWi/kltQBqjdgqz0lERPqDQYoIwNncUnwdnw0AWDqhL0zkrfOr4e/eCTYqBUoq63Aym7OcExEZGwYp6vA0GhGLbjaYj+/ngkHdu7Tac5vIZbpZzvfz9B4RkdFhkKIO77sTl3EyuwQWpnK8M9an1Z+/4fQel4shIjI+DFLUoZVW1eGDPdoG81dH9oKj9f03mN9qqJcD5DIBaVcrkHO9stWfn4iIpCN5kFqzZg08PT1hZmYGf39/HD58+I7jV69eDR8fH6hUKnh7e2PTpk1NxqxatQre3t5QqVRwc3PD/PnzUV1drbvfw8MDgiA0uc2dO1c3RhRFLFmyBC4uLlCpVBg6dCiSk5Nb742TXvh4XxqKbtSih70FZgZ5tslr2JgrEOCuXfD4QAqPShERGRNJg9TWrVsxb948vPPOOzh58iQefvhhhIaGIjs7u9nx0dHRCA8Px5IlS5CcnIylS5di7ty5+PHHH3VjtmzZggULFmDx4sVISUnB559/jq1btyI8PFw3JiEhAXl5ebrbvn37AACTJ0/Wjfnwww+xcuVKfPrpp0hISICTkxNGjRqF8vLyNvo0qL2du1KGTceyAAARE3xhatJ2vw4Nk3Me4HIxRERGRRBFUbJrsgMDAzFgwABER0frtvn4+GDixImIiopqMj4oKAjBwcH46KOPdNvmzZuHxMREHDlyBADw8ssvIyUlBQcOHNCNef311xEfH3/bo13z5s3Drl27kJ6eDkEQIIoiXFxcMG/ePLz99tsAgJqaGjg6OuKDDz7A7Nmz7+r9lZWVwcbGBqWlpbC2tr6rx1D7EEURT352DAlZxRjr54zVTw1o09e7UFCBkSsPwVQuw4l3R8FSadKmr0dERC13L9/fkh2Rqq2tRVJSEkaPHt1o++jRoxEXF9fsY2pqamBm1riHRaVSIT4+HnV12iU4QkJCkJSUhPj4eABARkYGYmNjMXbs2NvWsXnzZjz33HMQBO2aapmZmcjPz29Um1KpxJAhQ25bGxmW7adykZBVDJWibRrMb9XD3gIeXcxRq9bgCGc5JyIyGpIFqcLCQqjVajg6Ojba7ujoiPz8/GYfM2bMGKxfvx5JSUkQRRGJiYnYsGED6urqUFhYCACYOnUqli1bhpCQECgUCvTo0QPDhg3DggULmn3O7du3o6SkBDNnztRta3j9e6kN0Aa9srKyRjfSP+XVdYiM1TaYvzy8J1xsVW3+moIgYDgXMSYiMjqSN5s3HAVqIIpik20NFi1ahNDQUAwaNAgKhQITJkzQBSC5XA4AOHjwIJYvX441a9bgxIkT2LZtG3bt2oVly5Y1+5yff/45QkND4eLicl+1AUBUVBRsbGx0Nzc3t9uOJems2p+Oa+U18LSzwKyH26bBvDkNfVK/pBZAw1nOiYiMgmRBys7ODnK5vMkRnoKCgiZHghqoVCps2LABlZWVyMrKQnZ2Njw8PGBlZQU7OzsA2rA1Y8YMzJo1C35+fpg0aRIiIyMRFRUFjUbT6PkuXbqE/fv3Y9asWY22Ozk5AcA91QYA4eHhKC0t1d1ycnLu7sOgdpN2tRxfxmUBABaH9YHSRN5urz3QozOslCYorKjF75dL2u11iYio7UgWpExNTeHv76+7Yq7Bvn37EBQUdMfHKhQKuLq6Qi6XIyYmBuPGjYNMpn0rlZWVuj83kMvlEEURt/bVf/HFF3BwcGjSP+Xp6QknJ6dGtdXW1uLQoUN3rE2pVMLa2rrRjfSHKIp4d8dZqDUiRvdxxFBvh3Z9fVMTGR7x0s5y/jOv3iMiMgqSXjr02muvYcaMGQgICMDgwYOxdu1aZGdnY86cOQC0R3hyc3N1c0WlpaUhPj4egYGBKC4uxsqVK3H27Fls3LhR95xhYWFYuXIl+vfvj8DAQFy4cAGLFi3C+PHjdaf/AECj0eCLL77As88+CxOTxh+DIAiYN28eIiMj0atXL/Tq1QuRkZEwNzfH9OnT2+GTobbw4+k8/JZxHUoTGRaN6yNJDSN8HLD7TB4OpBTg9dHektRAREStR9IgNWXKFBQVFSEiIgJ5eXnw9fVFbGws3N3dAQB5eXmN5pRSq9VYsWIFUlNToVAoMGzYMMTFxcHDw0M3ZuHChRAEAQsXLkRubi7s7e0RFhaG5cuXN3rt/fv3Izs7G88991yztb311luoqqrCSy+9hOLiYgQGBuKnn36ClZVV638Q1OZu1NRj+e5zAICXhvaEW2dzSeoY6u0AQQDO5ZXhSklVuzS6ExFR25F0Hiljx3mk9EfUnhR8digD3Tqb46f5j8BM0X69Ubd6PDoOSZeK8d5EXzw9yF2yOoiIqHkGMY8UUXu5UFCBzw9nAtA2mEsZooA/zHLO5WKIiAwegxQZNVEUsWRnMuo1Iob3dsAIn9tfddleRtycT+roxSJU1tZLXA0REd0PBikyav89m48jFwphaiLD4jBpGsxv5eVoia62KtTWaxB3oUjqcoiI6D4wSJHRqqytx7Jd2gbzOY90h3sXC4kr0hIEASN1ixjz9B4RkSFjkCKjteaXi7hSWo2utiq8OLSn1OU0Mtznf8vF8HoPIiLDxSBFRimz8AbW/poBAFg0rg9UptI2mN8q0LMzzE3lKCivQfIVrslIRGSoGKTI6IiiiKU/JqNWrcEjXvYY01f6BvNbmSnkeLiXdlmj/bx6j4jIYDFIkdHZn1KAg6nXoJALWBLW544LTUup4eo9LhdDRGS4GKTIqFTXqbH0x2QAwKyHu6O7vaXEFd3e0N7adfdOXy5FQVm1xNUQEVFLMEiRUYk+eBGXi6vgbGOG/xuuXw3mt3KwMkM/N1sAPCpFRGSoGKTIaGQXVSL60EUAwMKxfWBuKulSkndlRO+GaRAYpIiIDBGDFBmNiF3nUFuvQVCPLviLn5PU5dyV4TeD1JH0QlTXqSWuhoiI7hWDFBmFX84XYH/KVZjIBERM6Ku3Dea36utiDSdrM1TVqXEsg7OcExEZGgYpMnjVdWosudlg/lyIJ3o6WElc0d0TBAHDb85y/nMKT+8RERkaBikyeOsPZ+BSUSUcrJR4ZUQvqcu5Zw19Uj+f5yznRESGhkGKDNrl4kp8+ssFAMA7Y31gqdT/BvNbBfe0g5lChtySKpzPL5e6HCIiugcMUmTQlu9OQXWdBg95dsb4fi5Sl9MiZgo5gntoZznnNAhERIaFQYoM1uH0a9hzNh9yA2swb05Dn9QBLhdDRGRQGKTIINXWa7B4p7bB/JnB7ujtZC1xRfenYbmYkzklKKyokbgaIiK6WwxSZJA2HM1ExrUbsLM0xfxRXlKXc9+cbMzQ18UaoggcTL0mdTlERHSXGKTI4OSVVuGTA+kAgAWhPrA2U0hcUesY4dOwiDFP7xERGQoGKTI4y3enoLJWDX/3Tnisf1epy2k1DdMg/JpWiNp6jcTVEBHR3WCQIoMSd7EQu07nQSYAERP6QiYz3AbzW/l1tYG9lRIVNfWIz7wudTlERHQXGKTIYNSpNVi8Q9tg/lSgO/q62EhcUeuSyQQM925YxJin94iIDAGDFBmMjXFZSC+oQGcLU7wx2lvqctrE/6ZB4CznRESGgEGKDEJBWTVW7dc2mL/9qDdszI2jwfxWIT3tYCqXIft6JS5eq5C6HCIi+hMMUmQQovacR0VNPfq52WKyv5vU5bQZC6UJBvfoAkB7VIqIiPQbgxTpvfjM6/jhZC4EAVhmZA3mzRnxh9N7RESk3xikSK/VqzV4d8dZAMDUgd3wgKuttAW1g+E3p0FIvHQdJZW1EldDRER3wiBFem3zb5dwPr8ctuYKvDnGOBvMb+XayRy9naygEYFDaZzlnIhInzFIkd66Vl6DFfvSAABvjPZGZwtTiStqPw1Hpfbz9B4RkV5jkCK99eF/z6O8uh6+Xa0x7aFuUpfTrhr6pA6lFqBOzVnOiYj0FYMU6aWkS8X4T9JlAMDS8b6QG3mD+a0edOuEzhamKKuuR9KlYqnLISKi22CQIr2j1ohYvFPbYD7Z3xX+7p0krqj9yWUChnrbAwAOpHCWcyIifcUgRXrn6/hsnM0tg5WZCd4O7S11OZIZ0dsRAHDgPPukiIj0FYMU6ZXrN2rxj72pAIDXR3nBzlIpcUXSecTLDiYyARnXbiCz8IbU5RARUTMYpEivfLT3PEqr6tDbyQpPD3KXuhxJWZkpENi9MwCe3iMi0lcMUqQ3fs8pQUxCDgBg2URfmMj513P4zdN7P/P0HhGRXuI3FekFjUbEuzvOQhSBSf27YqBHZ6lL0gsjb06DEJ95HWXVdRJXQ0REt2KQIr3wbWIOfr9cCkulCcI7cIP5rdy7WKCHvQXqNSJ+5SznRER6h0GKJFdSWYsP/nseADBvZC84WJtJXJF+Gelz8/QeZzknItI7DFIkuRU/paG4sg5ejpZ4NshD6nL0TsNyMb+kFkCtESWuhoiI/ohBiiR1NrcUW45fAqCdwVzBBvMm/N07wUalQHFlHU5mc5ZzIiJ9wm8tkkxDg7lGBML6uWBwjy5Sl6SXTOSy/81yzqv3iIj0CoMUSaJOrcE728/iRHYJzE3leOcvPlKXpNcaTu9xPikiIv1iInUB1PGUVNbipS0nEHexCIIALBnfF042bDC/k6FeDpDLBKRdrUDO9Uq4dTaXuiQiIgKPSFE7y7hWgUlr4hB3sQgWpnKsfyYATwa4SV2W3rMxVyDg5uLNnJyTiEh/MEhRuzl6oRATVx9FZuENdLVV4fuXgjDi5qX99OdG3Jyccz9P7xER6Q0GKWoXW45fwjMb4lFWXY8B3Wyx4+Vg9Haylrosg9KwXMzxjOuoqKmXuBoiIgL0IEitWbMGnp6eMDMzg7+/Pw4fPnzH8atXr4aPjw9UKhW8vb2xadOmJmNWrVoFb29vqFQquLm5Yf78+aiurm40Jjc3F08//TS6dOkCc3NzPPjgg0hKStLdP3PmTAiC0Og2aNCg1nnTHUi9WoMlO5Pxzg9nodaImNS/K75+YRDsLJVSl2ZwethbwKOLOWrVGhxJL5S6HCIigsTN5lu3bsW8efOwZs0aBAcH47PPPkNoaCjOnTuHbt26NRkfHR2N8PBwrFu3DgMHDkR8fDxeeOEFdOrUCWFhYQCALVu2YMGCBdiwYQOCgoKQlpaGmTNnAgA+/vhjAEBxcTGCg4MxbNgw7NmzBw4ODrh48SJsbW0bvd6jjz6KL774Qvezqalp23wQRqqsug7/9/VJHLq5tMmbY7zx0tAeEARB4soMkyAIGN7bERuOZuJAylU86uskdUlERB2eIIqiZFMlBwYGYsCAAYiOjtZt8/HxwcSJExEVFdVkfFBQEIKDg/HRRx/pts2bNw+JiYk4cuQIAODll19GSkoKDhw4oBvz+uuvIz4+Xne0a8GCBTh69Ogdj37NnDkTJSUl2L59e4vfX1lZGWxsbFBaWgpr6451Giu7qBLPb0xAekEFzBQyfPzkgwj1c5a6LIN39EIhnlp/HHaWpoj/+0jIZAylRESt7V6+vyU7tVdbW4ukpCSMHj260fbRo0cjLi6u2cfU1NTAzKzxZfIqlQrx8fGoq6sDAISEhCApKQnx8fEAgIyMDMTGxmLs2LG6x+zcuRMBAQGYPHkyHBwc0L9/f6xbt67J6x08eBAODg7w8vLCCy+8gIKCO18tVVNTg7Kyska3jig+8zomrD6C9IIKOFmb4bs5QQxRrWSgR2dYKU1QWFGL07mlUpdDRNThSRakCgsLoVar4ejY+KotR0dH5OfnN/uYMWPGYP369UhKSoIoikhMTMSGDRtQV1eHwkJtz8jUqVOxbNkyhISEQKFQoEePHhg2bBgWLFige56MjAxER0ejV69e2Lt3L+bMmYNXXnmlUb9VaGgotmzZgp9//hkrVqxAQkIChg8fjpqamtu+p6ioKNjY2Ohubm4d77L+/yTm4Kn1v6G4sg4PuNpgx8vB8O1qI3VZRsPURIZHvG7Ocs6r94iIJCd5s/mt/TKiKN62h2bRokUIDQ3FoEGDoFAoMGHCBF3/k1wuB6A9irR8+XKsWbMGJ06cwLZt27Br1y4sW7ZM9zwajQYDBgxAZGQk+vfvj9mzZ+OFF15odIpxypQpGDt2LHx9fREWFoY9e/YgLS0Nu3fvvu17CQ8PR2lpqe6Wk5PT0o/F4Kg1IqJiU/Dmd6dRpxYx1s8ZW/82GI7WnGiztf1vlnPOJ0VEJDXJgpSdnR3kcnmTo08FBQVNjlI1UKlU2LBhAyorK5GVlYXs7Gx4eHjAysoKdnZ2ALRha8aMGZg1axb8/PwwadIkREZGIioqChqNBgDg7OyMPn36NHpuHx8fZGdn37ZeZ2dnuLu7Iz09/bZjlEolrK2tG906ghs19Zj9VRI++zUDAPDKiF7417T+UJnKJa7MOA3r7QBBAM7llSGvtErqcoiIOjTJgpSpqSn8/f2xb9++Rtv37duHoKCgOz5WoVDA1dUVcrkcMTExGDduHGQy7VuprKzU/bmBXC6HKIpo6KsPDg5GampqozFpaWlwd3e/7WsWFRUhJycHzs7s9fmj3JIqPPHvY9ifchWmJjL8c+qDeG2UF5ug21BnC1MM6Kad5ZxHpYiIpCXp9AevvfYaZsyYgYCAAAwePBhr165FdnY25syZA0B7qiw3N1fXu5SWlob4+HgEBgaiuLgYK1euxNmzZ7Fx40bdc4aFhWHlypXo378/AgMDceHCBSxatAjjx4/Xnf6bP38+goKCEBkZiSeffBLx8fFYu3Yt1q5dCwCoqKjAkiVL8Pjjj8PZ2RlZWVn4+9//Djs7O0yaNKmdPyX9dSK7GH/blITCihrYWSqx7hl/9L/5BU9ta3hvByRdKsbP5wvw9KDb/weAiIjalqRBasqUKSgqKkJERATy8vLg6+uL2NhY3ZGhvLy8Rqfb1Go1VqxYgdTUVCgUCgwbNgxxcXHw8PDQjVm4cCEEQcDChQuRm5sLe3t7hIWFYfny5boxAwcOxA8//IDw8HBERETA09MTq1atwlNPPQVAewTrzJkz2LRpE0pKSuDs7Ixhw4Zh69atsLKyap8PR8/tOJWLN787jdp6DXycrbH+2QB0tVVJXVaHMdLHER/tTcXRC4WoqlXzNCoRkUQknUfK2BnjPFIajYhV+9Pwyc8XAGi/0P859UFYKCXN5B2OKIoI+eAX5JZUYf0zARjZh2sWEhG1FoOYR4oMT1WtGv/3zUldiJo9pDs+m+HPECUBQRB0ixgfOM8+KSIiqTBI0V25WlaNKWuPYfeZPCjkAj564gGEh/pAzqZyyYzw0R6F+vn8VfDAMhGRNHgogf7U2dxSPL8xAVfLatDJXIHPZgTgIc/OUpfV4QV6doa5qRxXy2qQfKWME58SEUmAR6TojvacycMT/47D1bIa9HKwxI65IQxResJMIcfDvbTzp3EaBCIiaTBIUbNEUcSnP6fjxS0nUF2nwRAve3z/UhC6dTGXujT6gxG9/3d6j4iI2h9P7VET1XVqhG87gx9O5gIAZgZ5YOFYH5jImbv1zdDe2nX3fr9cioKyajhwSR4ionbFb0Zq5Fp5Daav+w0/nMyFXCbgvYm+WDK+L0OUnnKwMkM/N1sAwC+pPL1HRNTe+O1IOufzyzBx9VGcyC6BtZkJNj33EGfNNgAjuIgxEZFkGKQIAHAg5SoeXxOH3JIqeNpZ4Ie5wQjuaSd1WXQXht8MUofTC1Fdp5a4GiKijoVBqoMTRRHrfs3ArE2JuFGrxuDuXfDDS0HoYW8pdWl0l/q6WMPJ2gxVdWr8llEkdTlERB0Kg1QHVluvwYLvz2B5bApEEZj2UDdsev4h2JqbSl0a3QNBEDD85iznP3OWcyKidsUg1UEV36jFjM+PY2tiDmQC8O64Poic5AsFm8oN0h/7pDjLORFR++H0Bx3QhYIKPL8xAZeKKmGpNMG/pvfHMG8Hqcui+xDc0w5mChlyS6qQerUcvZ2MY5FsIiJ9x8MPHcyvadcwac1RXCqqhGsnFba9FMQQZQTMFHIE9+As50RE7Y1BqgPZGJeFv36ZgPLqegz06IQdc4Ph5WgldVnUShr6pA6kcJZzIqL2wiDVAdSrNVi0/SwW70yGWiPi8QGu2DwrEF0slVKXRq2oYbmYkzklKKqokbgaIqKOgUHKyJVW1eGvXybgq98uQRCAtx/tjX9MfgBKE7nUpVErc7IxQ18Xa4gicDD1mtTlEBF1CAxSRiyr8AYmrTmKw+mFUCnk+PfT/nhxaA8IgiB1adRGdFfvcRFjIqJ2wSBlpI5dLMLENUeRce0GnG3M8N2LgzGmr5PUZVEbG+GjPb33a1ohaus1EldDRGT8GKSMUEx8NmZ8fhwllXXo52aLHXOD0dfFRuqyqB34dbWBnaUSFTX1SMi6LnU5RERGj0HKiKg1It7bdQ4Ltp1BvUbEuAecsfVvg+BgbSZ1adROZDIBw3vbAwD28+o9IqI2xyBlJMqr6/DCpkSsP5IJAJg3shf+Na0/zBRsKu9oGk7vcZZzIqK2x5nNjUDO9UrM2piI1KvlUJrI8I/J/RDWz0XqskgiIT3tYCqXIft6JS5eu4GeDlyAmoiorfCIlIFLunQdE1cfRerVcthbKbF19mCGqA7OQmmCQT26AODknEREbY1ByoBtO3EZ09YeR9GNWvRxtsbOl4PxoJut1GWRHhjZMMv5eS4XQ0TUlhikDJBGI+LD/57Ha9/+jlq1BqP7OOK7FwfD2UYldWmkJ4bfnE8q6VIxSiprJa6GiMh4MUgZoIU7zmLNwYsAgJeG9sC/n/aHuSnb3eh/XDuZo7eTFdQaEYfSOMs5EVFbYZAyQE/4u8JKaYIVk/vhrUd7QybjTOXUVMNRqQMpPL1HRNRWGKQM0IBunXDk7eF43N9V6lJIj4242Sd1MLUAdWrOck5E1BYYpAyUjblC6hJIzz3o1gmdLUxRVl2PpEvFUpdDRGSUGKSIjJRcJmCot3aW85959R4RUZtgkCIyYiN6a2c553IxRERtg0GKyIg94mUHE5mAjGs3kFl4Q+pyiIiMDoMUkRGzMlMgsHtnADy9R0TUFhikiIzc8N4Nixjz9B4RUWtjkCIycg3LxcRnXkdZdZ3E1RARGRcGKSIj597FAj3sLVCvEXE4rVDqcoiIjAqDFFEHMMKHp/eIiNoCgxRRBzDi5nIxv6QWQK0RJa6GiMh4MEgRdQD+7p1gbWaC4so6nMrhLOdERK2FQYqoAzCRyzDUW3tUaj8XMSYiajUMUkQdRMMixj8zSBERtRoGKaIOYoiXPeQyAalXy5FzvVLqcoiIjAKDFFEHYWtuCn/3TgA4yzkRUWthkCLqQBom5zzAIEVE1CoYpIg6kIblYn67WIQbNfUSV0NEZPgYpIg6kB72FvDoYo5atQaH0znLORHR/WKQIupABEHQHZX6+TxnOSciul+SB6k1a9bA09MTZmZm8Pf3x+HDh+84fvXq1fDx8YFKpYK3tzc2bdrUZMyqVavg7e0NlUoFNzc3zJ8/H9XV1Y3G5Obm4umnn0aXLl1gbm6OBx98EElJSbr7RVHEkiVL4OLiApVKhaFDhyI5Obl13jSRhHTTIJy/Bg1nOSciui+SBqmtW7di3rx5eOedd3Dy5Ek8/PDDCA0NRXZ2drPjo6OjER4ejiVLliA5ORlLly7F3Llz8eOPP+rGbNmyBQsWLMDixYuRkpKCzz//HFu3bkV4eLhuTHFxMYKDg6FQKLBnzx6cO3cOK1asgK2trW7Mhx9+iJUrV+LTTz9FQkICnJycMGrUKJSXl7fZ50HUHgZ6dIaV0gSFFTU4nVsqdTlERAZNEEVRsv+SBgYGYsCAAYiOjtZt8/HxwcSJExEVFdVkfFBQEIKDg/HRRx/pts2bNw+JiYk4cuQIAODll19GSkoKDhw4oBvz+uuvIz4+Xne0a8GCBTh69Ohtj36JoggXFxfMmzcPb7/9NgCgpqYGjo6O+OCDDzB79uy7en9lZWWwsbFBaWkprK2t7+oxRO1h7pYT2H0mD68M74nXRntLXQ4RkV65l+9vyY5I1dbWIikpCaNHj260ffTo0YiLi2v2MTU1NTAzM2u0TaVSIT4+HnV1dQCAkJAQJCUlIT4+HgCQkZGB2NhYjB07VveYnTt3IiAgAJMnT4aDgwP69++PdevW6e7PzMxEfn5+o9qUSiWGDBly29qIDMnw3pwGgYioNUgWpAoLC6FWq+Ho6Nhou6OjI/Lz85t9zJgxY7B+/XokJSVBFEUkJiZiw4YNqKurQ2Gh9gqkqVOnYtmyZQgJCYFCoUCPHj0wbNgwLFiwQPc8GRkZiI6ORq9evbB3717MmTMHr7zyiq7fquH176U2QBv0ysrKGt2I9NGw3g4QBCD5ShnySqukLoeIyGBJ3mwuCEKjn0VRbLKtwaJFixAaGopBgwZBoVBgwoQJmDlzJgBALpcDAA4ePIjly5djzZo1OHHiBLZt24Zdu3Zh2bJluufRaDQYMGAAIiMj0b9/f8yePRsvvPBCo1OM91obAERFRcHGxkZ3c3Nzu+vPgag9dbYwxYBunOWciOh+SRak7OzsIJfLmxzhKSgoaHIkqIFKpcKGDRtQWVmJrKwsZGdnw8PDA1ZWVrCzswOgDVszZszArFmz4Ofnh0mTJiEyMhJRUVHQaDQAAGdnZ/Tp06fRc/v4+Oia3J2cnADgnmoDgPDwcJSWlupuOTk59/CJELWvhtN7XMSYiKjlJAtSpqam8Pf3x759+xpt37dvH4KCgu74WIVCAVdXV8jlcsTExGDcuHGQybRvpbKyUvfnBnK5HKIooqGvPjg4GKmpqY3GpKWlwd3dHQDg6ekJJyenRrXV1tbi0KFDd6xNqVTC2tq60Y1IX4300f6n4MiFQlTVqiWuhojIMJlI+eKvvfYaZsyYgYCAAAwePBhr165FdnY25syZA0B7hCc3N1fXu5SWlob4+HgEBgaiuLgYK1euxNmzZ7Fx40bdc4aFhWHlypXo378/AgMDceHCBSxatAjjx4/Xnf6bP38+goKCEBkZiSeffBLx8fFYu3Yt1q5dC0B7Sm/evHmIjIxEr1690KtXL0RGRsLc3BzTp09v50+JqG14OVqiq60KuSVViLtYiBE+tz/aSkREzZM0SE2ZMgVFRUWIiIhAXl4efH19ERsbqzsylJeX12hOKbVajRUrViA1NRUKhQLDhg1DXFwcPDw8dGMWLlwIQRCwcOFC5Obmwt7eHmFhYVi+fLluzMCBA/HDDz8gPDwcERER8PT0xKpVq/DUU0/pxrz11luoqqrCSy+9hOLiYgQGBuKnn36ClZVV238wRO1AEASM8HHApmOXcOB8AYMUEVELSDqPlLHjPFKk7w6lXcOzG+LhZG2GY+HD73gxBRFRR2EQ80gRkfQCPTvD3FSO/LJqJF/hdB1ERPeqRUHqiSeewPvvv99k+0cffYTJkyffd1FE1D7MFHKE9NRe8cppEIiI7l2LgtShQ4cazRTe4NFHH8Wvv/5630URUftpuHrvQMpViSshIjI8LQpSFRUVMDU1bbJdoVBwNm8iAzO0tz0A4PfLpSgor5a4GiIiw9KiIOXr64utW7c22R4TE9Nkoksi0m8OVmbo52oDADh4/prE1RARGZYWTX+waNEiPP7447h48SKGDx8OADhw4AC++eYb/Oc//2nVAomo7Y3wccTvl0uxP+UqnhzIpY2IiO5Wi45IjR8/Htu3b8eFCxfw0ksv4fXXX8fly5exf/9+TJw4sZVLJKK21rBczJELhaiu4yznRER3q8UTco4dO7bZhnMiMjx9XazhZG2G/LJqHM+8jiFe9lKXRERkEFp0RCohIQHHjx9vsv348eNITEy876KIqH0JgoDhPtqjUrx6j4jo7rUoSM2dOxc5OTlNtufm5mLu3Ln3XRQRtb8RN0/v7Tt3FWoNFzwgIrobLQpS586dw4ABA5ps79+/P86dO3ffRRFR+wvuaQcblQJ5pdU4cqFQ6nKIiAxCi4KUUqnE1atND//n5eXBxETSdZCJqIXMFHI8NqArAOCb49l/MpqIiIAWBqlRo0YhPDwcpaWlum0lJSX4+9//jlGjRrVacUTUvqY91A0AsD/lKgrKODknEdGfaVGQWrFiBXJycuDu7o5hw4Zh2LBh8PT0RH5+PlasWNHaNRJRO/FytEKAeyfUa0T8J+my1OUQEem9FgWprl274vTp0/jwww/Rp08f+Pv745///CfOnDkDNzdO5kdkyKbePCoVk5ANDZvOiYjuqMUNTRYWFggJCUG3bt1QW1sLANizZw8A7YSdRGSYxvo5Y+mPyci5XoW4i0UI6WUndUlERHqrRUEqIyMDkyZNwpkzZyAIAkRRhCAIuvvVas6MTGSoVKZyPNa/KzYeu4Rv4rMZpIiI7qBFp/ZeffVVeHp64urVqzA3N8fZs2dx6NAhBAQE4ODBg61cIhG1t2mB2tN7e5Pzca28RuJqiIj0V4uC1LFjxxAREQF7e3vIZDLI5XKEhIQgKioKr7zySmvXSETtrLeTNR50s0W9RsT3J9h0TkR0Oy0KUmq1GpaWlgAAOzs7XLlyBQDg7u6O1NTU1quOiCQzvaHpPD4bosimcyKi5rQoSPn6+uL06dMAgMDAQHz44Yc4evQoIiIi0L1791YtkIikMa6fMyyVJsgqqsSxjCKpyyEi0kstClILFy6ERqMBALz33nu4dOkSHn74YcTGxuKTTz5p1QKJSBrmpiaY2N8FAPBNfNO1NYmICBDEVjpmf/36dXTq1KnR1XsdXVlZGWxsbFBaWgpra2upyyG6Z8lXSjH2kyMwlctwLHw4ulgqpS6JiKjN3cv3d4uOSDWnc+fODFFERqaviw0ecLVBrVqDbSdypS6HiEjvtFqQIiLj1LD+3jcJbDonIroVgxQR3VFYPxdYmMqRce0G4jOvS10OEZFeYZAiojuyVJpg/INdAQDfxGdLXA0RkX5hkCKiP9Uwp1Ts2XwU36iVuBoiIv3BIEVEf8rP1QZ9XaxRW6/BtpNsOiciasAgRUR3Rdd0zpnOiYh0GKSI6K5MeNAFKoUcFwoqkHSpWOpyiIj0AoMUEd0VKzMFxvfTznT+NZvOiYgAMEgR0T2Y+pAbAGD36TyUVtZJXA0RkfQYpIjorj3oZoveTlaoqdfgh5OXpS6HiEhyDFJEdNcEQcD0wIam8xw2nRNRh8cgRUT3ZMKDXWGmkCH1ajlO5pRIXQ4RkaQYpIjontioFBj3gLbp/JvjbDonoo6NQYqI7tm0m03nP56+grJqNp0TUcfFIEVE92xAt07wcrREdZ0GOzjTORF1YAxSRHTPBEHQzXT+NZvOiagDY5AiohaZ1L8rlCYypOSV4fTlUqnLISKSBIMUEbWIrbkpxvo5A9Cuv0dE1BExSBFRi029eXpv5+9XUM6mcyLqgBikiKjFBnp0Qg97C1TWqrHz9ytSl0NE1O4YpIioxf7YdM7Te0TUETFIEdF9eXyAK0zlMpzNLcMZNp0TUQfDIEVE96WThSke9XUCAHyTwKNSRNSxMEgR0X1rOL2342QubtTUS1wNEVH7YZAiovs2qHtneNpZ4EatGj+y6ZyIOhDJg9SaNWvg6ekJMzMz+Pv74/Dhw3ccv3r1avj4+EClUsHb2xubNm1qMmbVqlXw9vaGSqWCm5sb5s+fj+rqat39S5YsgSAIjW5OTk6NnmPmzJlNxgwaNKh13jSRkdE2nWvX3/smIUfiaoiI2o+JlC++detWzJs3D2vWrEFwcDA+++wzhIaG4ty5c+jWrVuT8dHR0QgPD8e6deswcOBAxMfH44UXXkCnTp0QFhYGANiyZQsWLFiADRs2ICgoCGlpaZg5cyYA4OOPP9Y9V9++fbF//37dz3K5vMnrPfroo/jiiy90P5uamrbWWycyOo8PcMVHe1Pxe04Jkq+Uoq+LjdQlkZ4oraxD8pVSGMNCQp3MTdHHxVrqMkiPSBqkVq5cieeffx6zZs0CoD2StHfvXkRHRyMqKqrJ+K+++gqzZ8/GlClTAADdu3fHb7/9hg8++EAXpI4dO4bg4GBMnz4dAODh4YFp06YhPj6+0XOZmJg0OQp1K6VS+adjiEiri6USo/s6YffpPMTE52DZRAYpAmrq1Xji33FIL6iQupRW8++nB+BRX2epyyA9IVmQqq2tRVJSEhYsWNBo++jRoxEXF9fsY2pqamBmZtZom0qlQnx8POrq6qBQKBASEoLNmzcjPj4eDz30EDIyMhAbG4tnn3220ePS09Ph4uICpVKJwMBAREZGonv37o3GHDx4EA4ODrC1tcWQIUOwfPlyODg43PY91dTUoKamRvdzWVnZXX0WRMZi+kPdsPt0HrafzEX4X3rD3FTS/6uRHthwJAvpBRUwN5XDrZO51OXclxu19bhcXIWIH8/hES97/v0mABIGqcLCQqjVajg6Ojba7ujoiPz8/GYfM2bMGKxfvx4TJ07EgAEDkJSUhA0bNqCurg6FhYVwdnbG1KlTce3aNYSEhEAURdTX1+PFF19sFNgCAwOxadMmeHl54erVq3jvvfcQFBSE5ORkdOnSBQAQGhqKyZMnw93dHZmZmVi0aBGGDx+OpKQkKJXKZuuLiorC0qVLW+kTIjI8g7t3gXsXc1wqqsSu03l4MsBN6pJIQnmlVfjXz+kAgGUTfPG4v6vEFd2fqlo1Rq48hNySKqz+5QLeHNNb6pJID0jebC4IQqOfRVFssq3BokWLEBoaikGDBkGhUGDChAm6/qeGHqeDBw9i+fLlWLNmDU6cOIFt27Zh165dWLZsme55QkND8fjjj8PPzw8jR47E7t27AQAbN27UjZkyZQrGjh0LX19fhIWFYc+ePUhLS9ONbU54eDhKS0t1t5wcNt1SxyKTCZg6UNvfGMOZzju893anoLJWjQD3TnhsQFepy7lvKlM5Fo3rAwBY92smMgtvSFwR6QPJgpSdnR3kcnmTo08FBQVNjlI1UKlU2LBhAyorK5GVlYXs7Gx4eHjAysoKdnZ2ALRha8aMGZg1axb8/PwwadIkREZGIioqChqNptnntbCwgJ+fH9LT029br7OzM9zd3e84RqlUwtrautGNqKN5wt8VJjIBJ7JLcD6fp7c7qrgLhdh9Og8yAVg6oe9t/4NsaMb0dcQjXvaoVWuwZGcyRNEYWujpfkgWpExNTeHv7499+/Y12r5v3z4EBQXd8bEKhQKurq6Qy+WIiYnBuHHjIJNp30plZaXuzw3kcjlEUbztX/iamhqkpKTA2fn2zYNFRUXIycm54xgiAuytlBjVR/ufoZh4HpXtiOrUGizemQwAeHqQu1FdwSkIApaE9YFCLuBQ2jXsO3dV6pJIYpKe2nvttdewfv16bNiwASkpKZg/fz6ys7MxZ84cANpTZc8884xufFpaGjZv3oz09HTEx8dj6tSpOHv2LCIjI3VjwsLCEB0djZiYGGRmZmLfvn1YtGgRxo8frzv998Ybb+DQoUPIzMzE8ePH8cQTT6CsrEzXkF5RUYE33ngDx44dQ1ZWFg4ePIiwsDDY2dlh0qRJ7fgJERmmhpnOt524jKpatcTVUHv78qi2wbyLhSleH+UtdTmtrru9JWY9rL04KWLXOVTX8e94RybpJQdTpkxBUVERIiIikJeXB19fX8TGxsLd3R0AkJeXh+zs//VZqNVqrFixAqmpqVAoFBg2bBji4uLg4eGhG7Nw4UIIgoCFCxciNzcX9vb2CAsLw/Lly3VjLl++jGnTpqGwsBD29vYYNGgQfvvtN93ryuVynDlzBps2bUJJSQmcnZ0xbNgwbN26FVZWVu3z4RAZsJCednDtpMLl4irEnskz+CZjunsFZdVYtT8NAPD2o71hY66QuKK28X/De2L7yVxcLq5C9MGLmD/KS+qSSCKCyBO8baasrAw2NjYoLS1lvxR1OKt/uYCP9qZioEcn/GfOnU/Xk/GYF3MS209dwYNuttj2YhBkMuPojWrO7tN5mPv1CZiayLB//hB062LY0zvQ/9zL97fkV+0RkXGa7O8KuUxAQlYx0q+WS10OtYPjGUXYfuoKBAGImNDXqEMUAPzFzwlBPbqgtl6DiF3JUpdDEmGQIqI24WBthhG9tRPYfsOmc6NX/4cG82kPdcMDrrbSFtQOBEFAxIS+MJEJ2J9SgJ/Ps/G8I2KQIqI2My1Q23T+/YnLbMg1cl/9dgnn88tha67Am6ONr8H8dno6WOG5EE8AwNIf2XjeETFIEVGbeaSXPbraqlBaVYf/nm1+xQIyfNfKa7DyJ22D+ZtjvNHJomMt8P7KiF5wsFLiUlEl1v2aIXU51M4YpIiozchlAqYM1C4T8w1nOjda7+85j/Kaevh1tdHNbN+RWCpN8M5YHwDA6oMXcLm4UuKKqD0xSBFRm5oc4AqZABzPvI6L1yqkLodaWdKl6/j+xGUA2gZzuZE3mN/O+H4ueMizM6rrNHhvV4rU5VA7YpAiojblbKPC8JtN51x/z7ioNSLe3aFtMH8ywBX9u3WSuCLpNDSey2UC/pucj1/TrkldErUTBikianMNM51/l3QZNfVsxjUWXx+/hOQrZbA2M8Hbj/aWuhzJ9XayxjODtRM7L9mZzL/rHQSDFBG1uSFe9nC2MUNxZR32JvMScWNQVFGDj/amAgDeGOONLpZKiSvSD/NHecHO0hQZhTew4UiW1OVQO2CQIqI2ZyKX4ckAbdM5T+8Zh4/2pqKsuh4+ztaY/lDHazC/HWszBRaEahvP//VzOvJKqySuiNoagxQRtYsnB7pBEIC4i0XILLwhdTl0H07llGBronaS1WUT+sJEzq+SP3qsf1f4u3dCZa0a7+1m47mx499+ImoXXW1VGOplDwCISeBRKUOl0Yh4d8dZiCLw2ICuCPDoLHVJekcm0zaeywTtenxxFwqlLonaEIMUEbUbXdN54mXU1mskroZaYmtiDk5fLoWV0gQLQtlgfjt9XWzw9CBt4/nincmoU/Pvu7FikCKidjO8twMcrJQoulGLfefYdG5oSipr8eF/zwMA5o3ygoOVmcQV6bfXR3mjs4Up0gsq8OXRLKnLoTbCIEVE7aZR0zlP7xmcf/yUiuLKOng7WuHZm5f50+3ZmCvw9qPadQdX7U9DQVm1xBVRW2CQIqJ2NeVm0/nh9EJkF3EpDUNxNrcUW45rw+9SNpjftcn+bujnZosbtWpExrLx3BjxN4GI2pVbZ3M83ItN54ZEoxGx6GaD+fh+LhjUvYvUJRkMmUzAsgl9IQjA9lNXcDyjSOqSqJUxSBFRu5v+kPb03reJl9mEawC+P3EZJ7NLYGEq1y3OS3fvAVdb3WLOi3cmo55/540KgxQRtbsRPo6ws1SisKIGB1LYdK7PSqvq8P4ebYP5KyN6wdGaDeYt8dYYb9iaK3A+vxxf/XZJ6nKoFTFIEVG7U8hlmBzgCgD4Jj5H4mroTj7el4aiG7XoYW+BvwZ7Sl2OwepkYYo3Rmsbz1f+lIZr5TUSV0SthUGKiCQxdaD29N6v6deQc51N5/ooJa8Mm45lAQAiJvjC1IRfGfdj2kPd4NvVGuU19bqjfGT4+FtBRJJw72KBkJ52EEXg20QeldI3oqidwVwjAmP9nBHc007qkgyeXCYgYoIvAG3fWdKl6xJXRK2BQYqIJNMw0/nWhBw24OqZ7adykZBVDJWCDeataUC3Tnjy5mntd3ckQ60RJa6I7heDFBFJZlQfR3SxMEVBeQ1+Pl8gdTl0U3l1HSJjtaeeXh7eEy62KokrMi5vPdob1mYmSL5Shq+Ps/Hc0DFIEZFkTE1keMJf+7/zmASe3tMX/9yfjmvlNfC0s8Csh9lg3trsLJV4/Wbj+Ud7U1FUwcZzQ8YgRUSSmnKz6fxgagFyS6okrobSrpbji7gsAMDisD5QmsilLchIPRXYDT7O1iirrsdHe1OlLofuA4MUEUmqu70lBnfvAo0IfMujUpJqaDBXa0SM7uOIod4OUpdktEzkMkRM6AsA2JqYg1M5JdIWRC3GIEVEkpsWqG06/zaRTedS2nU6D79lXIfSRIZF4/pIXY7RG+jRGY/17wpRhPYKSTaeGyQGKSKS3Ji+juhkrkBeaTUOpV2TupwO6UZNPZbv1i6q+9LQnnDrbC5xRR3Dgr/0hqXSBKcvl2IrpwExSAxSRCQ5pYkcjw/gTOdS+uTndOSXVaNbZ3PMHtJd6nI6DAcrM8wb2QsA8OF/z6OkslbiiuheMUgRkV6YenNOqZ/PX0V+abXE1XQsFwoqsOFIJgBtg7mZgg3m7enZIA94OVqiuLIO//iJjeeGhkGKiPRCTwdLPOTZWdt0zlMc7UYURSz9MRl1ahHDeztghI+j1CV1OAq5TDfj+Zbj2TibWypxRXQvGKSISG9M/8NM55zxuX3892w+DqcXwtREhsVhbDCXyqDuXTC+nwtEEVjExnODwiBFRHrjUV8n2KgUyC2pwq/pbDpva1W1aizbdQ4AMOeR7nDvYiFxRR3b3//iAwtTOU5ml+D7E5elLofuEoMUEekNM4Ucjw3oCgCIic+WuBrjt/qXC7hSWo2utiq8OLSn1OV0eE42ZnhlhLbx/P0951FaVSdxRXQ3GKSISK80LGS8P6UABWVsOm8rmYU3sPbXDADAonF9oDJlg7k++GuwJ3rYW6DoRi0+3pcmdTl0FxikiEiveDlaIcC9E9QaEf9J4umNttDQYF6r1uARL3uM6csGc31haiLD0vHaxvNNx7Jw7kqZxBXRn2GQIiK903BU6pv4bDbdtoH9KQU4mHoNCrmAJWF9IAiC1CXRH4T0ssNf/JygEYHFO89CFPk7oM8YpIhI7/zFzxlWZia4XFyFIxcKpS7HqFTXqbH0x2QAwKyHu6O7vaXEFVFz3hnbByqFHAlZxdh+KlfqcugOGKSISO+oTOV4rP/NpvMENp23pn8fuojLxVVwtjHD/w1ng7m+6mqrwss3909k7HmUV7PxXF8xSBGRXmpYyPin5Ku4Vl4jcTXGIed6JaIPXgQALBzbB+amJhJXRHcy62FPeNpZ4Fp5Df65P13qcug2GKSISC/1drJG/262qNeI+I5N561i6Y/nUFOvQVCPLviLn5PU5dCfUJrIdZOkfhGXhbSr5RJXRM1hkCIivTVtoPaoVEwCm87v1y/nC7A/5SpMZAIiJvRlg7mBGOrtgFF9HKHWiHh3BxvP9RGDFBHprXH9nGGpNMGlokocyyiSuhyDVV2nxpKbDebPhXiip4OVxBXRvXh3XB8oTWT4LeM6dp3Ok7ocugWDFBHpLXNTE0zs7wJAOxUCtcz6wxm4VFQJByulbuZsMhxunc3x0s2Z55fvTsGNmnqJK6I/YpAiIr3WMKfU3uR8FFWw6fxeXS6uxKe/XAAAvDPWB5ZKNpgbotlDuqNbZ3Pkl1Xjk5/ZeK5PGKSISK/1dbFBP1cb1KlFLuTaAst3p6C6ToOHPDtjfD8XqcuhFjJTyPHuOG3j+YYjmbhQUCFxRdSAQYqI9N5U3UznOWy2vQeH069hz9l8yNlgbhRG9nHE8N4OqFNrl/jh74J+kDxIrVmzBp6enjAzM4O/vz8OHz58x/GrV6+Gj48PVCoVvL29sWnTpiZjVq1aBW9vb6hUKri5uWH+/Pmorv7f4qdLliyBIAiNbk5OjS8FFkURS5YsgYuLC1QqFYYOHYrk5OTWedNEdE/C+rnAwlSOzMIb+C3jutTlGITaeg0W79T+m/XMYHf0drKWuCJqDYvD+sBULsPh9EL892y+1OUQJA5SW7duxbx58/DOO+/g5MmTePjhhxEaGors7OabSqOjoxEeHo4lS5YgOTkZS5cuxdy5c/Hjjz/qxmzZsgULFizA4sWLkZKSgs8//xxbt25FeHh4o+fq27cv8vLydLczZ840uv/DDz/EypUr8emnnyIhIQFOTk4YNWoUyss5jwdRe7NUmmD8g5zp/F5sOJqJjGs3YGdpivmjvKQuh1qJexcLzB7SHQCwbNc5VNWqJa6IJA1SK1euxPPPP49Zs2bBx8cHq1atgpubG6Kjo5sd/9VXX2H27NmYMmUKunfvjqlTp+L555/HBx98oBtz7NgxBAcHY/r06fDw8MDo0aMxbdo0JCYmNnouExMTODk56W729va6+0RRxKpVq/DOO+/gscceg6+vLzZu3IjKykp8/fXXbfNhENEdTb95em/PmXwU36iVuBr9lldahU8OaBuSF4T6wNpMIXFF1JpeGtoTXW1VuFJajdU3LyQg6UgWpGpra5GUlITRo0c32j569GjExcU1+5iamhqYmZk12qZSqRAfH4+6Ou06RCEhIUhKSkJ8fDwAICMjA7GxsRg7dmyjx6Wnp8PFxQWenp6YOnUqMjIydPdlZmYiPz+/UW1KpRJDhgy5bW1E1Lb8XG3g29UatWoNm87/xPLdKaisVcPfvZNuzUIyHipTORbdbDxf+2sGMgtvSFxRxyZZkCosLIRarYajo2Oj7Y6OjsjPb/6875gxY7B+/XokJSVBFEUkJiZiw4YNqKurQ2GhdoX4qVOnYtmyZQgJCYFCoUCPHj0wbNgwLFiwQPc8gYGB2LRpE/bu3Yt169YhPz8fQUFBKCrSTvjX8Pr3UhugDXplZWWNbkTUeqYObGg6z2aj7W3EXSzErtN5kAlAxIS+kMnYYG6MxvR1xMO97FCr1rDxXGKSN5vfehWJKIq3vbJk0aJFCA0NxaBBg6BQKDBhwgTMnDkTACCXywEABw8exPLly7FmzRqcOHEC27Ztw65du7Bs2TLd84SGhuLxxx+Hn58fRo4cid27dwMANm7c2OLaACAqKgo2Nja6m5ub2919CER0VyY86AKVQo6L124gIatY6nL0Tp1ag8U7tA3mTwW6o6+LjcQVUVsRBAFLx/eFQi7gYOo17E8pkLqkDkuyIGVnZwe5XN7kCE9BQUGTI0ENVCoVNmzYgMrKSmRlZSE7OxseHh6wsrKCnZ0dAG3YmjFjBmbNmgU/Pz9MmjQJkZGRiIqKgkajafZ5LSws4Ofnh/R0bU9BwxV891IbAISHh6O0tFR3y8nJubsPg4juipWZQjcXUgxnOm9iY1wW0gsq0NnCFG+M9pa6HGpj3e0tMethbeP50h+TUV3HxnMpSBakTE1N4e/vj3379jXavm/fPgQFBd3xsQqFAq6urpDL5YiJicG4ceMgk2nfSmVlpe7PDeRyOURRvO2hz5qaGqSkpMDZ2RkA4OnpCScnp0a11dbW4tChQ3esTalUwtrautGNiFrXtEDt6b1dZ/JQUsmm8wYFZdVYtV/7n8G3H/WGjTkbzDuC/xveE842ZrhcXIXogxelLqdDkvTU3muvvYb169djw4YNSElJwfz585GdnY05c+YA0B7heeaZZ3Tj09LSsHnzZqSnpyM+Ph5Tp07F2bNnERkZqRsTFhaG6OhoxMTEIDMzE/v27cOiRYswfvx43em/N954A4cOHUJmZiaOHz+OJ554AmVlZXj22WcBaA+Zzps3D5GRkfjhhx9w9uxZzJw5E+bm5pg+fXo7fkJEdKt+rjbo7WSF2noNfjiZK3U5eiNqz3lU1NSjn5stJvuzraCjMDc1wTtjfQAA0YcuIruoUuKKOh5JF12aMmUKioqKEBERgby8PPj6+iI2Nhbu7u4AgLy8vEZzSqnVaqxYsQKpqalQKBQYNmwY4uLi4OHhoRuzcOFCCIKAhQsXIjc3F/b29ggLC8Py5ct1Yy5fvoxp06ahsLAQ9vb2GDRoEH777Tfd6wLAW2+9haqqKrz00ksoLi5GYGAgfvrpJ1hZcdV0IikJgoDpgd3w7o5kfBOfjZlBHh1+xu74zOv44WQuBAFYxgbzDmesnzO+7pGNuItFiNh1DuufDZC6pA5FENnq32bKyspgY2OD0tJSnuYjakWlVXUIjNyP6joNvn9xMPzdO0tdkmTq1RqM+9cRnM8vx7SHuiHqMT+pSyIJpF8tR+g/D6NeI+KLmQMxrLeD1CUZtHv5/pb8qj0iontlo1Jg3APapvNv4jv2RR2bf7uE8/nlsDVX4K0xbDDvqHo5WuGvwR4AgCVsPG9XDFJEZJCm3ZzpfNfpKyitqpO4GmlcK6/Bin1pAIA3Rnujk4WpxBWRlF4d6QUHKyUuFVVi/eGMP38AtQoGKSIySAO62cLL0RLVdRrsONUxm84/+O95lFfXw7ertS5YUsdlqfxf4/mnv1zA5WI2nrcHBikiMkiCIOjCw9fHO95M50mXivFdknapnIgJvpCzwZwAjO/ngoc8O6O6ToPlu1OkLqdDYJAiIoM1qX9XKE1kOJ9fjlM5JVKX027UGhGLd54FAEz2d8WAbp0kroj0hSAIiJjQF3KZgD1n83E4/ZrUJRk9BikiMli25qYY66edSDemAzWdfx2fjbO5ZbA2M8Hbob2lLof0TG8nazwzWDudz+Kdyaitb35VD2odDFJEZNAaZjrf+fsVlFcbf9P59Ru1+MfeVADA66O9YWeplLgi0kfzR3nBztIUGdduYMPRTKnLMWoMUkRk0ALcO6GngyWq6tTYceqK1OW0uY/2nkdpVR16O1nhqUA2mFPzrM0UWBCqbTz/5EA68kqrJK7IeDFIEZFBEwQBUwdql0Qx9qbz33NKEJOgPYW5bKIvTOT8J5xu77H+XeHv3gmVtWo2nrch/hYSkcF7fIArTOUynMsrw5ncUqnLaRMajYh3d5yFKGq/IAd6dNzZ3OnuyGTaxnOZAOw6nYe4i4VSl2SUGKSIyOB1sjBFqJ8TAOOd6fzbxBz8frkUlkoTLGCDOd2lvi42eCrwZuP5jmTUqdl43toYpIjIKEwdeLPp/FQuKmrqJa6mdZVU1uKD/54HAMwb2QsO1mYSV0SG5I3R3uhsYYr0ggpsjMuSuhyjwyBFREZhUPfO8LSzwI1aNX783biazlf8lIbiyjp4OVri2SAPqcshA2NjrsDbj2rXYVy1Px0FZdUSV2RcGKSIyChoZzrXNp1/E58tcTWt52xuKbYcvwQAWDreFwo2mFMLTPZ3Qz83W1TU1CNqz3mpyzEq/I0kIqPx+ABXKOQCTl8uxVkjaDpvaDDXiEBYPxcM7tFF6pLIQMlkApZN6AtBAH44mYv4zOtSl2Q0TKQugIiotXSxVGJMXyfsOp2H6EMXMd3AF/I9mV2ME9klsDCV452/+EhdDhm4B1xtMXVgN3wTn413d5zFrv8L4RQarYBBioiMyrSHumHX6TzsvnkzBq+M6AUnGzaY0/17c4w39pzNw/n8crz+n9/xweMPwEwhl7osg8YgRURGZXD3LpgS4GY0ixh7OVnhr8GeUpdBRqKzhSmWT/TDKzEnsePUFeRcr8RnMwJgb8WlhlpKEI15GmCJlZWVwcbGBqWlpbC2tpa6HCIiIgDA0QuFeHFzEsqq69HVVoX1zwbAx5nfUw3u5fubJ0eJiIg6mOCedtg+NxiedhbILanCE9Fx2H/uqtRlGSQGKSIiog6ou70lfngpCEE9uuBGrRovfJWIdb9mGPV6lW2BQYqIiKiDsjU3xcbnHsK0h7pBFIHlsSl4+/vTqK3nUjJ3i0GKiIioA1PIZYic5It3x/WBTAC+TbyMGZ8fR/GNWqlLMwgMUkRERB2cIAh4LsQTn88cCEulCY5nXsfENUdxoaBc6tL0HoMUERERAQCGeTtg20tBcOuswqWiSkxaE4df065JXZZeY5AiIiIiHS9HK2x/KRgDPTqhvLoef/0yARvjsqQuS28xSBEREVEjXSyV2DwrEI8PcIVaI2LxzmQs2n4W9Wo2od+KQYqIiIiaUJrI8Y/JD2BBaG8IAvDVb5cw84sElFbVSV2aXmGQIiIiomYJgoA5Q3rg30/7Q6WQ48iFQkxacxRZhTekLk1vMEgRERHRHY3p64TvXhwMZxszZFy7gQmrj+LYxSKpy9ILDFJERET0p/q62GDHy8Ho52aL0qo6zPj8OGLis6UuS3IMUkRERHRXHKzMsPVvgxDWzwX1GhELtp3Be7vOQa3puMvKMEgRERHRXTNTyPHJ1Acxf6QXAGD9kUy8sCkR5dUdswmdQYqIiIjuiSAIeHVkL3w6vT+UJjL8fL4AT0QfQ871SqlLa3cMUkRERNQi4x5wwbezB8PBSonUq+WYuPooErOuS11Wu2KQIiIiohbr52aLHS8Ho6+LNYpu1GL6uuPYduKy1GW1GwYpIiIiui/ONir8Z85gjOnriFq1Bq99+zs+/O95aDpAEzqDFBEREd03c1MTRD/lj7nDegAA1hy8iJe2nEBlbb3ElbUtBikiIiJqFTKZgDfH9MbKJ/vBVC7Df5PzMfnfx5BXWiV1aW2GQYqIiIha1WMDXPH1C4HoYmGK5CtlmPDpUfyeUyJ1WW2CQYqIiIhaXYBHZ2yfGwxvRysUlNfgyc+OYdfpK1KX1eoYpIiIiKhNuHU2x3cvDsbw3g6oqdfg5a9P4p/70yGKxtOEziBFREREbcbKTIF1zwRgVognAODj/Wl4JeYUquvUElfWOhikiIiIqE3JZQIWjuuD9x/zg4lMwI+/X8HUtb+hoLxa6tLuG4MUERERtYupD3XDV88HwtZcgVM5JZj46VGcu1ImdVn3hUGKiIiI2s3gHl2w/aVgdLe3wJXSajzx7zj8lJwvdVktxiBFRERE7crDzgI/vBiMkJ52qKxVY/bmJPz70EWDbEJnkCIiIqJ2Z2OuwBd/HYgZg9whisD7e87jze9Oo6besJrQGaSIiIhIEgq5DMsm+iJiQl/IZQK+S7qMp9cfR1FFjdSl3TXJg9SaNWvg6ekJMzMz+Pv74/Dhw3ccv3r1avj4+EClUsHb2xubNm1qMmbVqlXw9vaGSqWCm5sb5s+fj+rq5q8MiIqKgiAImDdvXqPtM2fOhCAIjW6DBg1q8fskIiKi5j0z2ANfzBwIK6UJErKKMXHNUaRdLZe6rLsiaZDaunUr5s2bh3feeQcnT57Eww8/jNDQUGRnZzc7Pjo6GuHh4ViyZAmSk5OxdOlSzJ07Fz/++KNuzJYtW7BgwQIsXrwYKSkp+Pzzz7F161aEh4c3eb6EhASsXbsWDzzwQLOv9+ijjyIvL093i42NbZ03TkRERI084mWPH+YGoVtnc+Rcr8Lja+LwS2qB1GX9KUmD1MqVK/H8889j1qxZ8PHxwapVq+Dm5obo6Ohmx3/11VeYPXs2pkyZgu7du2Pq1Kl4/vnn8cEHH+jGHDt2DMHBwZg+fTo8PDwwevRoTJs2DYmJiY2eq6KiAk899RTWrVuHTp06Nft6SqUSTk5Oulvnzp1b780TERFRIz0drLBjbjAe8uyM8pp6PP9lAjYcydTrJnTJglRtbS2SkpIwevToRttHjx6NuLi4Zh9TU1MDMzOzRttUKhXi4+NRV1cHAAgJCUFSUhLi4+MBABkZGYiNjcXYsWMbPW7u3LkYO3YsRo4cedsaDx48CAcHB3h5eeGFF15AQcGdk3FNTQ3Kysoa3YiIiOjudbIwxebnA/FkgCs0IhCx6xze2X4WdWqN1KU1S7IgVVhYCLVaDUdHx0bbHR0dkZ/f/HwSY8aMwfr165GUlARRFJGYmIgNGzagrq4OhYWFAICpU6di2bJlCAkJgUKhQI8ePTBs2DAsWLBA9zwxMTE4ceIEoqKibltfaGgotmzZgp9//hkrVqxAQkIChg8fjpqa2zfARUVFwcbGRndzc3O7l4+EiIiIAJiayPDB4w/gnb/4QBCAr49n49kN8SiprJW6tCYkbzYXBKHRz6IoNtnWYNGiRQgNDcWgQYOgUCgwYcIEzJw5EwAgl8sBaI8iLV++HGvWrMGJEyewbds27Nq1C8uWLQMA5OTk4NVXX8XmzZubHN36oylTpmDs2LHw9fVFWFgY9uzZg7S0NOzevfu2jwkPD0dpaanulpOTcy8fBREREd0kCAJeeKQ71s0IgIWpHHEXizBpTRwyrlVIXVojkgUpOzs7yOXyJkefCgoKmhylaqBSqbBhwwZUVlYiKysL2dnZ8PDwgJWVFezs7ABow9aMGTMwa9Ys+Pn5YdKkSYiMjERUVBQ0Gg2SkpJQUFAAf39/mJiYwMTEBIcOHcInn3wCExMTqNXNz1/h7OwMd3d3pKen3/Y9KZVKWFtbN7oRERFRy43s44jvXgxCV1sVMgtvYOLqozh6oVDqsnQkC1Kmpqbw9/fHvn37Gm3ft28fgoKC7vhYhUIBV1dXyOVyxMTEYNy4cZDJtG+lsrJS9+cGcrkcoihCFEWMGDECZ86cwalTp3S3gIAAPPXUUzh16pTuyNatioqKkJOTA2dn5/t410RERHSvfJytsX1uMAZ0s0VZdT2e2RCPLccvSV0WAMBEyhd/7bXXMGPGDAQEBGDw4MFYu3YtsrOzMWfOHADaU2W5ubm6uaLS0tIQHx+PwMBAFBcXY+XKlTh79iw2btyoe86wsDCsXLkS/fv3R2BgIC5cuIBFixZh/PjxkMvlsLKygq+vb6M6LCws0KVLF932iooKLFmyBI8//jicnZ2RlZWFv//977Czs8OkSZPa6dMhIiKiBvZWSnz9wiAs+P40tp+6gnd+OIsLBRV45y8+MJFL16kkaZCaMmUKioqKEBERgby8PPj6+iI2Nhbu7u4AgLy8vEZzSqnVaqxYsQKpqalQKBQYNmwY4uLi4OHhoRuzcOFCCIKAhQsXIjc3F/b29ggLC8Py5cvvui65XI4zZ85g06ZNKCkpgbOzM4YNG4atW7fCysqq1d4/ERER3T0zhRwfT3kQPR0s8Y+f0vDF0Sxcv1GLf07tL1lNgqjPkzMYuLKyMtjY2KC0tJT9UkRERK1oz5k8vPXdaXw2wx9BPe1a9bnv5ftb0iNSRERERC0R6ueMoB52sDFXSFqH5NMfEBEREbWE1CEKYJAiIiIiajEGKSIiIqIWYpAiIiIiaiEGKSIiIqIWYpAiIiIiaiEGKSIiIqIWYpAiIiIiaiEGKSIiIqIWYpAiIiIiaiEGKSIiIqIWYpAiIiIiaiEGKSIiIqIWYpAiIiIiaiETqQswZqIoAgDKysokroSIiIjuVsP3dsP3+J0wSLWh8vJyAICbm5vElRAREdG9Ki8vh42NzR3HCOLdxC1qEY1GgytXrsDKygqCIEhdjl4qKyuDm5sbcnJyYG1tLXU5HR73h37h/tAv3B/6pS33hyiKKC8vh4uLC2SyO3dB8YhUG5LJZHB1dZW6DINgbW3Nf5j0CPeHfuH+0C/cH/qlrfbHnx2JasBmcyIiIqIWYpAiIiIiaiEGKZKUUqnE4sWLoVQqpS6FwP2hb7g/9Av3h37Rl/3BZnMiIiKiFuIRKSIiIqIWYpAiIiIiaiEGKSIiIqIWYpCiNhcdHY0HHnhAN9fH4MGDsWfPHt39oihiyZIlcHFxgUqlwtChQ5GcnCxhxR1LVFQUBEHAvHnzdNu4T9rPkiVLIAhCo5uTk5Pufu6L9pebm4unn34aXbp0gbm5OR588EEkJSXp7uc+aV8eHh5NfkcEQcDcuXMBSL8/GKSozbm6uuL9999HYmIiEhMTMXz4cEyYMEH3F/3DDz/EypUr8emnnyIhIQFOTk4YNWqUbokdajsJCQlYu3YtHnjggUbbuU/aV9++fZGXl6e7nTlzRncf90X7Ki4uRnBwMBQKBfbs2YNz585hxYoVsLW11Y3hPmlfCQkJjX4/9u3bBwCYPHkyAD3YHyKRBDp16iSuX79e1Gg0opOTk/j+++/r7quurhZtbGzEf//73xJWaPzKy8vFXr16ifv27ROHDBkivvrqq6Ioitwn7Wzx4sViv379mr2P+6L9vf3222JISMht7+c+kd6rr74q9ujRQ9RoNHqxP3hEitqVWq1GTEwMbty4gcGDByMzMxP5+fkYPXq0boxSqcSQIUMQFxcnYaXGb+7cuRg7dixGjhzZaDv3SftLT0+Hi4sLPD09MXXqVGRkZADgvpDCzp07ERAQgMmTJ8PBwQH9+/fHunXrdPdzn0irtrYWmzdvxnPPPQdBEPRifzBIUbs4c+YMLC0toVQqMWfOHPzwww/o06cP8vPzAQCOjo6Nxjs6Ouruo9YXExODEydOICoqqsl93CftKzAwEJs2bcLevXuxbt065OfnIygoCEVFRdwXEsjIyEB0dDR69eqFvXv3Ys6cOXjllVewadMmAPz9kNr27dtRUlKCmTNnAtCP/cFFi6ldeHt749SpUygpKcH333+PZ599FocOHdLdLwhCo/GiKDbZRq0jJycHr776Kn766SeYmZnddhz3SfsIDQ3V/dnPzw+DBw9Gjx49sHHjRgwaNAgA90V70mg0CAgIQGRkJACgf//+SE5ORnR0NJ555hndOO4TaXz++ecIDQ2Fi4tLo+1S7g8ekaJ2YWpqip49eyIgIABRUVHo168f/vnPf+quTrr1fw4FBQVN/odBrSMpKQkFBQXw9/eHiYkJTExMcOjQIXzyyScwMTHRfe7cJ9KwsLCAn58f0tPT+fshAWdnZ/Tp06fRNh8fH2RnZwMA94mELl26hP3792PWrFm6bfqwPxikSBKiKKKmpgaenp5wcnLSXYUBaM+BHzp0CEFBQRJWaLxGjBiBM2fO4NSpU7pbQEAAnnrqKZw6dQrdu3fnPpFQTU0NUlJS4OzszN8PCQQHByM1NbXRtrS0NLi7uwMA94mEvvjiCzg4OGDs2LG6bXqxP9qlpZ06tPDwcPHXX38VMzMzxdOnT4t///vfRZlMJv7000+iKIri+++/L9rY2Ijbtm0Tz5w5I06bNk10dnYWy8rKJK684/jjVXuiyH3Snl5//XXx4MGDYkZGhvjbb7+J48aNE62srMSsrCxRFLkv2lt8fLxoYmIiLl++XExPTxe3bNkimpubi5s3b9aN4T5pf2q1WuzWrZv49ttvN7lP6v3BIEVt7rnnnhPd3d1FU1NT0d7eXhwxYoQuRImi9nLixYsXi05OTqJSqRQfeeQR8cyZMxJW3PHcGqS4T9rPlClTRGdnZ1GhUIguLi7iY489JiYnJ+vu575ofz/++KPo6+srKpVKsXfv3uLatWsb3c990v727t0rAhBTU1Ob3Cf1/hBEURTb59gXERERkXFhjxQRERFRCzFIEREREbUQgxQRERFRCzFIEREREbUQgxQRERFRCzFIEREREbUQgxQRERFRCzFIEREREbUQgxQR0W14eHhg1apVUpdBRHqMQYqIOrwvv/wStra2TbYnJCTgb3/7W5u/PgMbkeEykboAIiJ9ZW9vL3UJ96S2thampqZSl0HUofCIFBHpjaFDh+KVV17BW2+9hc6dO8PJyQlLliy5q8eWlpbib3/7GxwcHGBtbY3hw4fj999/193/+++/Y9iwYbCysoK1tTX8/f2RmJiIgwcP4q9//StKS0shCAIEQdC95q1HigRBwGeffYZx48bB3NwcPj4+OHbsGC5cuIChQ4fCwsICgwcPxsWLF3WPuXjxIiZMmABHR0dYWlpi4MCB2L9/f6P3fOnSJcyfP1/3+g2+//579O3bF0qlEh4eHlixYkWj9+zh4YH33nsPM2fOhI2NDV544QXU1tbi5ZdfhrOzM8zMzODh4YGoqKh72AtEdC8YpIhIr2zcuBEWFhY4fvw4PvzwQ0RERGDfvn13fIwoihg7dizy8/MRGxuLpKQkDBgwACNGjMD169cBAE899RRcXV2RkJCApKQkLFiwAAqFAkFBQVi1ahWsra2Rl5eHvLw8vPHGG7d9rWXLluGZZ57BqVOn0Lt3b0yfPh2zZ89GeHg4EhMTAQAvv/yybnxFRQX+8pe/YP/+/Th58iTGjBmDsLAwZGdnAwC2bdsGV1dXRERE6F4fAJKSkvDkk09i6tSpOHPmDJYsWYJFixbhyy+/bFTPRx99BF9fXyQlJWHRokX45JNPsHPnTnz77bdITU3F5s2b4eHhca+7gYjulkhEpCeGDBkihoSENNo2cOBA8e23377j4w4cOCBaW1uL1dXVjbb36NFD/Oyzz0RRFEUrKyvxyy+/bPbxX3zxhWhjY9Nku7u7u/jxxx/rfgYgLly4UPfzsWPHRADi559/rtv2zTffiGZmZnest0+fPuK//vWv276OKIri9OnTxVGjRjXa9uabb4p9+vRp9LiJEyc2GvN///d/4vDhw0WNRnPHGoiodfCIFBHplQceeKDRz87OzigoKLjjY5KSklBRUYEuXbrA0tJSd8vMzNSdZnvttdcwa9YsjBw5Eu+//36j028trc/R0REA4Ofn12hbdXU1ysrKAAA3btzAW2+9hT59+sDW1haWlpY4f/687ojU7aSkpCA4OLjRtuDgYKSnp0OtVuu2BQQENBozc+ZMnDp1Ct7e3njllVfw008/teh9EtHdYbM5EekVhULR6GdBEKDRaO74GI1GA2dnZxw8eLDJfQ1X4y1ZsgTTp0/H7t27sWfPHixevBgxMTGYNGlSi+tr6GdqbltDzW+++Sb27t2Lf/zjH+jZsydUKhWeeOIJ1NbW3vF1RFFs1C/VsO1WFhYWjX4eMGAAMjMzsWfPHuzfvx9PPvkkRo4cie++++4e3iUR3S0GKSIyeAMGDEB+fj5MTEzu2A/k5eUFLy8vzJ8/H9OmTcMXX3yBSZMmwdTUtNFRntZ0+PBhzJw5UxfYKioqkJWV1WhMc6/fp08fHDlypNG2uLg4eHl5QS6X3/E1ra2tMWXKFEyZMgVPPPEEHn30UVy/fh2dO3e+/zdERI3w1B4RGbyRI0di8ODBmDhxIvbu3YusrCzExcVh4cKFSExMRFVVFV5++WUcPHgQly5dwtGjR5GQkAAfHx8A2qvfKioqcODAARQWFqKysrLVauvZsye2bduGU6dO4ffff8f06dObHGHz8PDAr7/+itzcXBQWFgIAXn/9dRw4cADLli1DWloaNm7ciE8//fSOjfAA8PHHHyMmJgbnz59HWloa/vOf/8DJyanZebKI6P4xSBGRwRMEAbGxsXjkkUfw3HPPwcvLC1OnTkVWVhYcHR0hl8tRVFSEZ555Bl5eXnjyyScRGhqKpUuXAgCCgoIwZ84cTJkyBfb29vjwww9brbaPP/4YnTp1QlBQEMLCwjBmzBgMGDCg0ZiIiAhkZWWhR48eurmrBgwYgG+//RYxMTHw9fXFu+++i4iICMycOfOOr2dpaYkPPvgAAQEBGDhwILKyshAbGwuZjP/cE7UFQWzupDsRERER/Sn+F4WIiIiohRikiEjvbdmypdG0Bn+89e3bV+ryiKgD46k9ItJ75eXluHr1arP3KRQKuLu7t3NFRERaDFJERERELcRTe0REREQtxCBFRERE1EIMUkREREQtxCBFRERE1EIMUkREREQtxCBFRERE1EIMUkREREQtxCBFRERE1EL/D89/ehDqdOR9AAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "cross = []\n",
    "for i  in range(25, 75, 5):\n",
    "    rf = RandomForestClassifier(n_estimators=i+1,random_state=42)\n",
    "    rf.fit(x_train, y_train)\n",
    "    cross_score = cross_val_score(rf, x_train, y_train, cv=5).mean()\n",
    "    cross.append(cross_score)\n",
    "\n",
    "plt.plot(range(25, 75, 5),cross)\n",
    "plt.xlabel('n_estimators')\n",
    "plt.ylabel('acc')\n",
    "best_n_estimators=cross.index(max(cross))*5+25\n",
    "print(cross.index(max(cross))*5+25,max(cross))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b322a88-a886-4c46-9e64-43485329c447",
   "metadata": {},
   "source": [
    "#### GridSearch  \n",
    "**通过网格搜索和交叉验证来自动优化模型的超参数**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5db296bc-adfb-4e9f-9249-b9db2b4fd622",
   "metadata": {},
   "source": [
    "- 调整 max_depth"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "b2baa39b-59ad-4ae9-83dd-8854b7fedb26",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "best_param:  {'max_depth': 19}\n",
      "best_score:  0.986572438162544\n",
      "test_score:  0.9675121117127387\n"
     ]
    }
   ],
   "source": [
    "param_grid = {'max_depth' : np.arange(1,20,1)}\n",
    "#一般根据数据大小进行尝试，像该数据集 可从1-10 或1-20开始\n",
    "rf = RandomForestClassifier(n_estimators=42, random_state=42)\n",
    "RF = GridSearchCV(rf, param_grid, cv=5)   # 将k次的得分取平均得到最后的得分\n",
    "RF.fit(x_train, y_train)\n",
    "print('best_param: ', RF.best_params_)\n",
    "print('best_score: ', RF.best_score_)\n",
    "score = RF.score(X_test, y_test)\n",
    "print('test_score: ',score)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ceca123-f8d7-43f5-87ed-d0bde9b00720",
   "metadata": {},
   "source": [
    "- 调整 max_features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e70a324e-a90d-4b06-a613-9353399cd0a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "param_grid = {'max_features' : np.arange(5,15,1)}\n",
    "rf = RandomForestClassifier(n_estimators=42, max_depth=19, random_state=42)\n",
    "RF = GridSearchCV(rf, param_grid, cv=5)\n",
    "RF.fit(x_train, y_train)\n",
    "print('best_param: ', RF.best_params_)\n",
    "print('best_score: ', RF.best_score_)\n",
    "score = RF.score(X_test, y_test)\n",
    "print('test_score: ',score)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73320443-a159-4198-a7f8-e52d15ba561a",
   "metadata": {},
   "source": [
    "- 调整 min_samples_leaf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "e83ef5c6-3730-4b0b-8446-7515f3ca4756",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "best_param:  {'min_samples_leaf': 1}\n",
      "best_score:  0.9879858657243815\n",
      "test_score:  0.969506982046167\n"
     ]
    }
   ],
   "source": [
    "param_grid = {'min_samples_leaf' : np.arange(1,10,1)}\n",
    "#一般是从其最小值开始向上增加10或者20\n",
    "# 面对高维度高样本数据，如果不放心，也可以直接+50，对于大型数据可能需要增加200-300\n",
    "# 如果调整的时候发现准确率怎么都上不来，那可以放心大胆调一个很大的数据，大力限制模型的复杂度\n",
    "rf = RandomForestClassifier(n_estimators=42, max_depth=19, max_features=5, random_state=42)\n",
    "RF = GridSearchCV(rf, param_grid, cv=5)\n",
    "RF.fit(x_train, y_train)\n",
    "print('best_param: ', RF.best_params_)\n",
    "print('best_score: ', RF.best_score_)\n",
    "score = RF.score(X_test, y_test)\n",
    "print('test_score: ',score)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71c6b29e-47d2-486a-922e-ece4d939fa54",
   "metadata": {},
   "source": [
    "- 调整 criterion"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "c5524d1f-6d62-441b-bc71-403d0adda9c9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "best_param:  {'criterion': 'gini'}\n",
      "best_score:  0.9879858657243815\n",
      "test_score:  0.969506982046167\n"
     ]
    }
   ],
   "source": [
    "param_grid = {'criterion' :['gini','entropy']}\n",
    "rf = RandomForestClassifier(n_estimators=42, max_depth=19, max_features=5, min_samples_leaf=1, random_state=42)\n",
    "RF = GridSearchCV(rf, param_grid, cv=5)\n",
    "RF.fit(x_train, y_train)\n",
    "print('best_param: ', RF.best_params_)\n",
    "print('best_score: ', RF.best_score_)\n",
    "score = RF.score(X_test, y_test)\n",
    "print('test_score: ',score)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8e37d02d-419e-4692-8808-fde6357d6be6",
   "metadata": {},
   "source": [
    "### 最终模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "8e8f108e-96f3-4763-a818-3e55057b88f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "x_train_full = x_train_sm.copy()\n",
    "y_train_full = y_train_sm.copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "c99a39e8-6908-4d32-ab17-89900a783c13",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test AUC: 0.658383211409148\n"
     ]
    }
   ],
   "source": [
    "from sklearn import metrics\n",
    "rf = RandomForestClassifier(n_estimators=best_n_estimators, \n",
    "                            max_depth=19, \n",
    "                            max_features=5, \n",
    "                            min_samples_leaf=1, \n",
    "                            criterion='gini', \n",
    "                            random_state=42)\n",
    "rf.fit(x_train_full, y_train_full)\n",
    "\n",
    "# 用 predict_proba 得到正类(1)的概率\n",
    "y_prob = rf.predict_proba(X_test)[:, 1]\n",
    "# 计算 AUC\n",
    "auc = roc_auc_score(y_test, y_prob)\n",
    "print(\"Test AUC:\", auc)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4910dc47-7e0a-4fbc-a4ab-569ddf486878",
   "metadata": {},
   "source": [
    "## 预测"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dafbab04-b22d-4930-9e04-49111d09e8bf",
   "metadata": {},
   "source": [
    "- 数据处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "id": "25b15d83-0bc7-47e0-a4f5-117d41188082",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 复制数据，避免修改原始数据\n",
    "df_y6 = datas_manual_y6[df.columns].copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "9efda994-7c17-42de-9290-1d09abbd32d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用训练数据的中位数填充缺失值\n",
    "df_y6 = df_y6.fillna(df.median())\n",
    "X_test_y6 = df_y6.iloc[:,:-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "95971605-4cc8-42b2-b57f-f7120c01da27",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# 使用训练时保存的标准化器进行标准化\n",
    "X_test_y6_scaled = scaler.transform(X_test_y6)\n",
    "X_test_y6_scaled = pd.DataFrame(X_test_y6_scaled, columns=X_test_y6.columns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "id": "253b9a9f-2877-4630-bc47-7537b84e177a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 只保留训练时选定的特征\n",
    "X_test_y6_scaled = X_test_y6_scaled[feature_lst]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ecefa2a4-fe3c-41c0-81f7-5268ae9c55ad",
   "metadata": {},
   "source": [
    "- 模型预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "id": "ad332c67-a237-49cb-8a58-645276443d7a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用训练好的模型进行预测\n",
    "y_pred_prob = rf.predict_proba(X_test_y6_scaled)[:, 1]  # 获取正类的概率\n",
    "y_pred = rf.predict(X_test_y6_scaled)  # 获取预测类别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "id": "fc9419e7-7bd9-4187-89b0-9bb9c33a7c5f",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\柔莹\\AppData\\Local\\Temp\\ipykernel_19492\\3345145997.py:2: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
      "  datas_manual_y6['PRED_PROB'] = y_pred_prob\n",
      "C:\\Users\\柔莹\\AppData\\Local\\Temp\\ipykernel_19492\\3345145997.py:3: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
      "  datas_manual_y6['PRED_FLAG'] = y_pred\n"
     ]
    }
   ],
   "source": [
    "# 将预测结果添加到原始数据中\n",
    "datas_manual_y6['PRED_PROB'] = y_pred_prob\n",
    "datas_manual_y6['PRED_FLAG'] = y_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "id": "a48e2139-678f-40eb-9e90-3c4181bde767",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预测完成！前5个样本的预测结果：\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>TICKER_SYMBOL</th>\n",
       "      <th>PRED_PROB</th>\n",
       "      <th>PRED_FLAG</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>18060</th>\n",
       "      <td>4019</td>\n",
       "      <td>0.030769</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18061</th>\n",
       "      <td>4213</td>\n",
       "      <td>0.030546</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18062</th>\n",
       "      <td>8166</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18065</th>\n",
       "      <td>10375</td>\n",
       "      <td>0.015385</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18066</th>\n",
       "      <td>11737</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       TICKER_SYMBOL  PRED_PROB  PRED_FLAG\n",
       "18060           4019   0.030769        0.0\n",
       "18061           4213   0.030546        0.0\n",
       "18062           8166   0.000000        0.0\n",
       "18065          10375   0.015385        0.0\n",
       "18066          11737   0.000000        0.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 显示预测结果\n",
    "print(\"预测完成！前5个样本的预测结果：\")\n",
    "display(datas_manual_y6[['TICKER_SYMBOL', 'PRED_PROB', 'PRED_FLAG']].head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "356568cd-d648-4c04-94f6-a955ef7ea716",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 保存预测结果到CSV文件\n",
    "#datas_manual_y6.to_csv('第六年制造业企业财务造假预测结果.csv', index=False)\n",
    "#print(\"预测结果已保存到 '第六年制造业企业财务造假预测结果.csv'\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
